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

Commit 36960fda authored by Xiaowen Lei's avatar Xiaowen Lei Committed by Android (Google) Code Review
Browse files

Merge "Use ViewHierarchyAnimator to animate media container layout." into main

parents 83e9cef4 85bc534d
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.keyguard;

import static java.util.Collections.emptySet;

import android.animation.LayoutTransition;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Build;
@@ -79,14 +78,6 @@ public class KeyguardStatusView extends GridLayout {
        mKeyguardSlice = findViewById(R.id.keyguard_slice_view);

        mMediaHostContainer = findViewById(R.id.status_view_media_container);
        if (mMediaHostContainer != null) {
            LayoutTransition mediaLayoutTransition = new LayoutTransition();
            ((ViewGroup) mMediaHostContainer).setLayoutTransition(mediaLayoutTransition);
            mediaLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
            mediaLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
            mediaLayoutTransition.disableTransitionType(LayoutTransition.APPEARING);
            mediaLayoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING);
        }

        updateDark();
    }
+6 −23
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CL
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;

import android.animation.Animator;
import android.animation.LayoutTransition;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.content.res.Configuration;
@@ -50,14 +49,15 @@ import com.android.internal.jank.InteractionJankMonitor;
import com.android.keyguard.KeyguardClockSwitch.ClockSize;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.Dumpable;
import com.android.systemui.res.R;
import com.android.systemui.animation.ViewHierarchyAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.power.shared.model.ScreenPowerState;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.power.shared.model.ScreenPowerState;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
@@ -175,27 +175,10 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
                            return;
                        }

                        final LayoutTransition mediaLayoutTransition =
                                ((ViewGroup) mediaHostContainer).getLayoutTransition();
                        if (mediaLayoutTransition == null) return;

                        mediaLayoutTransition.enableTransitionType(LayoutTransition.CHANGING);
                        ViewHierarchyAnimator.Companion.animateNextUpdate(mediaHostContainer,
                                Interpolators.STANDARD, /* duration= */ 500L,
                                /* animateChildren= */ false);
                    });

            mediaHostContainer.addOnLayoutChangeListener(
                    (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
                        final LayoutTransition mediaLayoutTransition =
                                ((ViewGroup) mediaHostContainer).getLayoutTransition();
                        if (mediaLayoutTransition == null) return;
                        if (!mediaLayoutTransition.isTransitionTypeEnabled(
                                LayoutTransition.CHANGING)) {
                            return;
                        }
                        // Note: when this is called, the LayoutTransition is already been set up.
                        // Disables the LayoutTransition until it's explicitly enabled again.
                        mediaLayoutTransition.disableTransitionType(LayoutTransition.CHANGING);
                    }
            );
        }

        mDumpManager.registerDumpable(getInstanceName(), this);
+0 −2
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.animation.LayoutTransition;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
@@ -69,7 +68,6 @@ public class KeyguardStatusViewControllerBaseTest extends SysuiTestCase {

    @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
    @Mock protected FrameLayout mMediaHostContainer;
    @Mock protected LayoutTransition mMediaLayoutTransition;

    @Before
    public void setup() {
+35 −41
Original line number Diff line number Diff line
@@ -16,19 +16,24 @@

package com.android.keyguard;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.animation.LayoutTransition;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;

import com.android.app.animation.Interpolators;
import com.android.systemui.animation.ViewHierarchyAnimator;
import com.android.systemui.plugins.ClockConfig;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.res.R;
@@ -39,6 +44,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

import java.lang.reflect.Field;

@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner.class)
@@ -142,19 +149,7 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll
    }

    @Test
    public void onInit_addsOnLayoutChangeListenerToMediaHostContainer() {
        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
                mMediaHostContainer);

        mController.onInit();

        ArgumentCaptor<View.OnLayoutChangeListener> captor =
                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
        verify(mMediaHostContainer).addOnLayoutChangeListener(captor.capture());
    }

    @Test
    public void clockSwitchHeightChanged_mediaChangingLayoutTransitionEnabled() {
    public void clockSwitchHeightChanged_animatesMediaHostContainer() {
        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
                mMediaHostContainer);

@@ -167,6 +162,10 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll
        // Above here is the same as `onInit_addsOnLayoutChangeListenerToClockSwitch`.
        // Below here is the actual test.

        ViewHierarchyAnimator.Companion animator = ViewHierarchyAnimator.Companion;
        ViewHierarchyAnimator.Companion spiedAnimator = spy(animator);
        setCompanion(spiedAnimator);

        View.OnLayoutChangeListener listener = captor.getValue();

        mController.setSplitShadeEnabled(true);
@@ -174,17 +173,20 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll
        when(mKeyguardUpdateMonitor.isKeyguardVisible()).thenReturn(true);
        when(mMediaHostContainer.getVisibility()).thenReturn(View.VISIBLE);
        when(mMediaHostContainer.getHeight()).thenReturn(200);
        when(mMediaHostContainer.getLayoutTransition()).thenReturn(mMediaLayoutTransition);

        when(mKeyguardClockSwitch.getHeight()).thenReturn(0);
        listener.onLayoutChange(mKeyguardClockSwitch, /* left= */ 0, /* top= */ 0, /* right= */
                0, /* bottom= */ 0, /* oldLeft= */ 0, /* oldTop= */ 0, /* oldRight= */
                0, /* oldBottom = */ 200);
        verify(mMediaLayoutTransition).enableTransitionType(LayoutTransition.CHANGING);
        verify(spiedAnimator).animateNextUpdate(mMediaHostContainer,
                Interpolators.STANDARD, /* duration= */ 500L, /* animateChildren= */ false);

        // Resets ViewHierarchyAnimator.Companion to its original value
        setCompanion(animator);
    }

    @Test
    public void clockSwitchHeightNotChanged_mediaChangingLayoutTransitionNotEnabled() {
    public void clockSwitchHeightNotChanged_doesNotAnimateMediaOutputContainer() {
        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
                mMediaHostContainer);

@@ -197,6 +199,10 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll
        // Above here is the same as `onInit_addsOnLayoutChangeListenerToClockSwitch`.
        // Below here is the actual test.

        ViewHierarchyAnimator.Companion animator = ViewHierarchyAnimator.Companion;
        ViewHierarchyAnimator.Companion spiedAnimator = spy(animator);
        setCompanion(spiedAnimator);

        View.OnLayoutChangeListener listener = captor.getValue();

        mController.setSplitShadeEnabled(true);
@@ -204,36 +210,24 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll
        when(mKeyguardUpdateMonitor.isKeyguardVisible()).thenReturn(true);
        when(mMediaHostContainer.getVisibility()).thenReturn(View.VISIBLE);
        when(mMediaHostContainer.getHeight()).thenReturn(200);
        when(mMediaHostContainer.getLayoutTransition()).thenReturn(mMediaLayoutTransition);

        when(mKeyguardClockSwitch.getHeight()).thenReturn(200);
        listener.onLayoutChange(mKeyguardClockSwitch, /* left= */ 0, /* top= */ 0, /* right= */
                0, /* bottom= */ 0, /* oldLeft= */ 0, /* oldTop= */ 0, /* oldRight= */
                0, /* oldBottom = */ 200);
        verify(mMediaLayoutTransition, never()).enableTransitionType(LayoutTransition.CHANGING);
    }
        verify(spiedAnimator, never()).animateNextUpdate(any(), any(), anyLong(), anyBoolean());

    @Test
    public void onMediaHostContainerLayout_disablesChangingLayoutTransition() {
        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
                mMediaHostContainer);

        mController.onInit();

        ArgumentCaptor<View.OnLayoutChangeListener> captor =
                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
        verify(mMediaHostContainer).addOnLayoutChangeListener(captor.capture());

        // Above here is the same as `onInit_addsOnLayoutChangeListenerToMediaHostContainer`.
        // Below here is the actual test.

        View.OnLayoutChangeListener listener = captor.getValue();

        when(mMediaHostContainer.getLayoutTransition()).thenReturn(mMediaLayoutTransition);
        // Resets ViewHierarchyAnimator.Companion to its original value
        setCompanion(animator);
    }

        when(mMediaLayoutTransition.isTransitionTypeEnabled(LayoutTransition.CHANGING)).thenReturn(
                true);
        listener.onLayoutChange(mMediaHostContainer, 1, 2, 3, 4, 1, 2, 3, 4);
        verify(mMediaLayoutTransition).disableTransitionType(LayoutTransition.CHANGING);
    private void setCompanion(ViewHierarchyAnimator.Companion companion) {
        try {
            Field field = ViewHierarchyAnimator.class.getDeclaredField("Companion");
            field.setAccessible(true);
            field.set(null, companion);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
+0 −15
Original line number Diff line number Diff line
package com.android.keyguard

import android.animation.LayoutTransition
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -35,20 +34,6 @@ class KeyguardStatusViewTest : SysuiTestCase() {
                as KeyguardStatusView
    }

    @Test
    fun mediaViewHasLayoutTransitionInDisabledState() {
        val layoutTransition = (mediaView as ViewGroup).layoutTransition
        assertThat(layoutTransition).isNotNull()
        assertThat(layoutTransition.isTransitionTypeEnabled(LayoutTransition.CHANGE_APPEARING))
            .isFalse()
        assertThat(layoutTransition.isTransitionTypeEnabled(LayoutTransition.CHANGE_DISAPPEARING))
            .isFalse()
        assertThat(layoutTransition.isTransitionTypeEnabled(LayoutTransition.APPEARING)).isFalse()
        assertThat(layoutTransition.isTransitionTypeEnabled(LayoutTransition.DISAPPEARING))
            .isFalse()
        assertThat(layoutTransition.isTransitionTypeEnabled(LayoutTransition.CHANGING)).isFalse()
    }

    @Test
    fun setChildrenTranslationYExcludingMediaView_mediaViewIsNotTranslated() {
        val translationY = 1234f