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

Commit b6e14ca5 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve systemui unlockscreen jank issue" into main

parents 75639151 461cfbb7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1473,3 +1473,13 @@ flag {
       purpose: PURPOSE_BUGFIX
   }
}

flag {
   name: "check_lockscreen_gone_transition"
   namespace: "systemui"
   description: "Run notification pipeline when the lockscreen is not in gone transition for avoiding janky frames during unlocking animation"
   bug: "358301118"
   metadata {
       purpose: PURPOSE_BUGFIX
   }
}
+33 −5
Original line number Diff line number Diff line
@@ -20,8 +20,6 @@ import static com.google.common.truth.Truth.assertThat;

import static junit.framework.Assert.assertFalse;

import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;

import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -31,12 +29,16 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;

import android.platform.test.annotations.EnableFlags;
import android.testing.TestableLooper;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.compose.animation.scene.ObservableTransitionState;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.communal.shared.model.CommunalScenes;
import com.android.systemui.dump.DumpManager;
@@ -67,9 +69,6 @@ import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.FakeSystemClock;

import kotlinx.coroutines.flow.MutableStateFlow;
import kotlinx.coroutines.test.TestScope;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -79,6 +78,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.verification.VerificationMode;

import kotlinx.coroutines.flow.MutableStateFlow;
import kotlinx.coroutines.test.TestScope;

@SmallTest
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper
@@ -516,6 +518,32 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
        verifyStabilityManagerWasInvalidated(times(1));
    }

    @Test
    @EnableFlags(Flags.FLAG_CHECK_LOCKSCREEN_GONE_TRANSITION)
    public void testNotLockscreenInGoneTransition_invalidationCalled() {
        // GIVEN visual stability is being maintained b/c animation is playing
        mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava(
                mTestScope, new TransitionStep(
                        KeyguardState.LOCKSCREEN,
                        KeyguardState.GONE,
                        1f,
                        TransitionState.RUNNING),  /* validateStep = */ false);
        mTestScope.getTestScheduler().runCurrent();
        assertFalse(mNotifStabilityManager.isPipelineRunAllowed());

        // WHEN the animation has stopped playing
        mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava(
                mTestScope, new TransitionStep(
                        KeyguardState.LOCKSCREEN,
                        KeyguardState.GONE,
                        1f,
                        TransitionState.FINISHED),  /* validateStep = */ false);
        mTestScope.getTestScheduler().runCurrent();

        // invalidate is called, b/c we were previously suppressing the pipeline from running
        verifyStabilityManagerWasInvalidated(times(1));
    }

    @Test
    public void testNeverSuppressPipelineRunFromPanelCollapse_noInvalidationCalled() {
        // GIVEN animation is playing
+11 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.view.View
import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.core.view.updateMargins
import com.android.systemui.Flags
import com.android.systemui.compose.ComposeInitializer
import com.android.systemui.res.R

@@ -103,6 +104,8 @@ open class WindowRootView(

    private fun applyMargins() {
        val count = childCount
        val hasFlagsEnabled = Flags.checkLockscreenGoneTransition()
        var hasChildMarginUpdated = false
        for (i in 0 until count) {
            val child = getChildAt(i)
            if (child.layoutParams is LayoutParams) {
@@ -113,11 +116,18 @@ open class WindowRootView(
                            layoutParams.leftMargin != leftInset)
                ) {
                    layoutParams.updateMargins(left = leftInset, right = rightInset)
                    hasChildMarginUpdated = true
                    if (!hasFlagsEnabled) {
                        child.requestLayout()
                    }
                }
            }
        }
        if (hasFlagsEnabled && hasChildMarginUpdated) {
            // Request layout at once after all children's margins has updated
            requestLayout()
        }
    }

    /**
     * Returns `true` if this view is the true root of the view-hierarchy; `false` otherwise.
+10 −3
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import androidx.annotation.WorkerThread;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.Flags;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -813,11 +814,17 @@ public class NotificationLockscreenUserManagerImpl implements

    private void notifyNotificationStateChanged() {
        if (!Looper.getMainLooper().isCurrentThread()) {
            if (Flags.checkLockscreenGoneTransition()) {
                for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
                    mMainExecutor.execute(listener::onNotificationStateChanged);
                }
            } else {
                mMainExecutor.execute(() -> {
                    for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
                        listener.onNotificationStateChanged();
                    }
                });
            }
        } else {
            for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
                listener.onNotificationStateChanged();
+28 −2
Original line number Diff line number Diff line
@@ -22,15 +22,18 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.systemui.Dumpable;
import com.android.systemui.Flags;
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.shared.model.Edge;
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.scene.shared.model.Scenes;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
@@ -85,6 +88,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
    private boolean mNotifPanelLaunchingActivity;
    private boolean mCommunalShowing = false;
    private boolean mLockscreenShowing = false;
    private boolean mLockscreenInGoneTransition = false;

    private boolean mPipelineRunAllowed;
    private boolean mReorderingAllowed;
@@ -158,6 +162,13 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
                            KeyguardState.LOCKSCREEN),
                    this::onLockscreenKeyguardStateTransitionValueChanged);
        }
        if (Flags.checkLockscreenGoneTransition()) {
            mJavaAdapter.alwaysCollectFlow(mKeyguardTransitionInteractor.isInTransition(
                            Edge.create(KeyguardState.LOCKSCREEN, Scenes.Gone),
                            Edge.create(KeyguardState.LOCKSCREEN, KeyguardState.GONE)),
                    this::onLockscreenInGoneTransitionChanged);
        }


        pipeline.setVisualStabilityManager(mNotifStabilityManager);
    }
@@ -239,7 +250,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
    private void updateAllowedStates(String field, boolean value) {
        boolean wasPipelineRunAllowed = mPipelineRunAllowed;
        boolean wasReorderingAllowed = mReorderingAllowed;
        mPipelineRunAllowed = !isPanelCollapsingOrLaunchingActivity();
        // No need to run notification pipeline when the lockscreen is in fading animation.
        mPipelineRunAllowed = !(isPanelCollapsingOrLaunchingActivity()
                || (Flags.checkLockscreenGoneTransition() && mLockscreenInGoneTransition));
        mReorderingAllowed = isReorderingAllowed();
        if (wasPipelineRunAllowed != mPipelineRunAllowed
                || wasReorderingAllowed != mReorderingAllowed) {
@@ -330,7 +343,6 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
                    updateAllowedStates("fullyDozed", fullyDozed);
                }
            };

    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
        @Override
        public void onFinishedGoingToSleep() {
@@ -353,6 +365,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
        pw.println("pipelineRunAllowed: " + mPipelineRunAllowed);
        pw.println("  notifPanelCollapsing: " + mNotifPanelCollapsing);
        pw.println("  launchingNotifActivity: " + mNotifPanelLaunchingActivity);
        if (Flags.checkLockscreenGoneTransition()) {
            pw.println("  lockscreenInGoneTransition: " + mLockscreenInGoneTransition);
        }
        pw.println("reorderingAllowed: " + mReorderingAllowed);
        pw.println("  sleepy: " + mSleepy);
        pw.println("  fullyDozed: " + mFullyDozed);
@@ -401,4 +416,15 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
        mLockscreenShowing = isShowing;
        updateAllowedStates("lockscreenShowing", isShowing);
    }

    private void onLockscreenInGoneTransitionChanged(boolean inGoneTransition) {
        if (!Flags.checkLockscreenGoneTransition()) {
            return;
        }
        if (inGoneTransition == mLockscreenInGoneTransition) {
            return;
        }
        mLockscreenInGoneTransition = inGoneTransition;
        updateAllowedStates("lockscreenInGoneTransition", mLockscreenInGoneTransition);
    }
}
Loading