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

Commit 41a04c24 authored by Julia Tuttle's avatar Julia Tuttle Committed by Android (Google) Code Review
Browse files

Merge changes I1d38dd58,I930d6306 into main

* changes:
  Flexiglass: visual stability on lockscreen
  Add VisualStabilityLog
parents ea743d22 98a3a75f
Loading
Loading
Loading
Loading
+71 −2
Original line number Diff line number Diff line
@@ -41,8 +41,12 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.communal.shared.model.CommunalScenes;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.data.repository.ShadeAnimationRepository;
import com.android.systemui.shade.data.repository.ShadeRepository;
@@ -91,6 +95,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Mock private HeadsUpManager mHeadsUpManager;
    @Mock private VisibilityLocationProvider mVisibilityLocationProvider;
    @Mock private VisualStabilityProvider mVisualStabilityProvider;
    @Mock private VisualStabilityCoordinatorLogger mLogger;

    @Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
    @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor;
@@ -128,7 +133,9 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
                mVisibilityLocationProvider,
                mVisualStabilityProvider,
                mWakefulnessLifecycle,
                mKosmos.getCommunalInteractor());
                mKosmos.getCommunalInteractor(),
                mKosmos.getKeyguardTransitionInteractor(),
                mLogger);
        mCoordinator.attach(mNotifPipeline);
        mTestScope.getTestScheduler().runCurrent();

@@ -240,6 +247,38 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
        assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
    }

    @Test
    public void testLockscreenPartlyShowing_groupAndSectionChangesNotAllowed() {
        // GIVEN the panel true expanded and device isn't pulsing
        setFullyDozed(false);
        setSleepy(false);
        setLockscreenShowing(0.5f);
        setPulsing(false);

        // THEN group changes are NOT allowed
        assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
        assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));

        // THEN section changes are NOT allowed
        assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
    }

    @Test
    public void testLockscreenFullyShowing_groupAndSectionChangesNotAllowed() {
        // GIVEN the panel true expanded and device isn't pulsing
        setFullyDozed(false);
        setSleepy(false);
        setLockscreenShowing(1.0f);
        setPulsing(false);

        // THEN group changes are NOT allowed
        assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
        assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));

        // THEN section changes are NOT allowed
        assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
    }

    @Test
    public void testPulsing_screenOff_groupAndSectionChangesNotAllowed() {
        // GIVEN the device is pulsing and screen is off
@@ -614,7 +653,37 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    }

    private void setPanelExpanded(boolean expanded) {
        mStatusBarStateListener.onExpandedChanged(expanded);
        setPanelExpandedAndLockscreenShowing(expanded, /* lockscreenShowing = */ 0.0f);
    }

    private void setLockscreenShowing(float lockscreenShowing) {
        setPanelExpandedAndLockscreenShowing(/* panelExpanded = */ false, lockscreenShowing);
    }

    private void setPanelExpandedAndLockscreenShowing(boolean panelExpanded,
            float lockscreenShowing) {
        if (SceneContainerFlag.isEnabled()) {
            mStatusBarStateListener.onExpandedChanged(panelExpanded);
            mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava(
                    mTestScope,
                    makeLockscreenTransitionStep(lockscreenShowing),
                    /* validateStep = */ false);
        } else {
            mStatusBarStateListener.onExpandedChanged(panelExpanded || lockscreenShowing > 0.0f);
        }
    }

    private TransitionStep makeLockscreenTransitionStep(float value) {
        if (value <= 0.0f) {
            return new TransitionStep(KeyguardState.GONE);
        } else if (value >= 1.0f) {
            return new TransitionStep(KeyguardState.LOCKSCREEN);
        } else {
            return new TransitionStep(
                    KeyguardState.GONE,
                    KeyguardState.LOCKSCREEN,
                    value,
                    TransitionState.RUNNING);
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -169,6 +169,14 @@ public class LogModule {
        return factory.create("NotifRemoteInputLog", 50 /* maxSize */, false /* systrace */);
    }

    /** Provides a logging buffer for all logs related to notification visual stability. */
    @Provides
    @SysUISingleton
    @VisualStabilityLog
    public static LogBuffer provideVisualStabilityLogBuffer(LogBufferFactory factory) {
        return factory.create("VisualStabilityLog", 50 /* maxSize */, false /* systrace */);
    }

    /** Provides a logging buffer for all logs related to keyguard media controller. */
    @Provides
    @SysUISingleton
+25 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.systemui.log.dagger

import javax.inject.Qualifier

/** A [com.android.systemui.log.LogBuffer] for visual stability-related messages. */
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class VisualStabilityLog
+33 −13
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator;

import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;

import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

@@ -29,7 +27,10 @@ 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.KeyguardState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
@@ -41,7 +42,6 @@ import com.android.systemui.statusbar.notification.collection.provider.VisualSta
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.Compile;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;

@@ -61,8 +61,6 @@ import javax.inject.Inject;
// TODO(b/204468557): Move to @CoordinatorScope
@SysUISingleton
public class VisualStabilityCoordinator implements Coordinator, Dumpable {
    public static final String TAG = "VisualStability";
    public static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
    private final DelayableExecutor mDelayableExecutor;
    private final HeadsUpManager mHeadsUpManager;
    private final SeenNotificationsInteractor mSeenNotificationsInteractor;
@@ -73,6 +71,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
    private final VisualStabilityProvider mVisualStabilityProvider;
    private final WakefulnessLifecycle mWakefulnessLifecycle;
    private final CommunalInteractor mCommunalInteractor;
    private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
    private final VisualStabilityCoordinatorLogger mLogger;

    private boolean mSleepy = true;
    private boolean mFullyDozed;
@@ -81,6 +81,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
    private boolean mNotifPanelCollapsing;
    private boolean mNotifPanelLaunchingActivity;
    private boolean mCommunalShowing = false;
    private boolean mLockscreenShowing = false;

    private boolean mPipelineRunAllowed;
    private boolean mReorderingAllowed;
@@ -109,7 +110,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
            VisibilityLocationProvider visibilityLocationProvider,
            VisualStabilityProvider visualStabilityProvider,
            WakefulnessLifecycle wakefulnessLifecycle,
            CommunalInteractor communalInteractor) {
            CommunalInteractor communalInteractor,
            KeyguardTransitionInteractor keyguardTransitionInteractor,
            VisualStabilityCoordinatorLogger logger) {
        mHeadsUpManager = headsUpManager;
        mShadeAnimationInteractor = shadeAnimationInteractor;
        mJavaAdapter = javaAdapter;
@@ -120,6 +123,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
        mStatusBarStateController = statusBarStateController;
        mDelayableExecutor = delayableExecutor;
        mCommunalInteractor = communalInteractor;
        mKeyguardTransitionInteractor = keyguardTransitionInteractor;
        mLogger = logger;

        dumpManager.registerDumpable(this);
    }
@@ -138,6 +143,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
                this::onLaunchingActivityChanged);
        mJavaAdapter.alwaysCollectFlow(mCommunalInteractor.isIdleOnCommunal(),
                this::onCommunalShowingChanged);
        mJavaAdapter.alwaysCollectFlow(mKeyguardTransitionInteractor.transitionValue(
                        KeyguardState.LOCKSCREEN),
                this::onLockscreenKeyguardStateTransitionValueChanged);

        pipeline.setVisualStabilityManager(mNotifStabilityManager);
    }
@@ -221,12 +229,12 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
        boolean wasReorderingAllowed = mReorderingAllowed;
        mPipelineRunAllowed = !isPanelCollapsingOrLaunchingActivity();
        mReorderingAllowed = isReorderingAllowed();
        if (DEBUG && (wasPipelineRunAllowed != mPipelineRunAllowed
                || wasReorderingAllowed != mReorderingAllowed)) {
            Log.d(TAG, "Stability allowances changed:"
                    + "  pipelineRunAllowed " + wasPipelineRunAllowed + "->" + mPipelineRunAllowed
                    + "  reorderingAllowed " + wasReorderingAllowed + "->" + mReorderingAllowed
                    + "  when setting " + field + "=" + value);
        if (wasPipelineRunAllowed != mPipelineRunAllowed
                || wasReorderingAllowed != mReorderingAllowed) {
            mLogger.logAllowancesChanged(
                    wasPipelineRunAllowed, mPipelineRunAllowed,
                    wasReorderingAllowed, mReorderingAllowed,
                    field, value);
        }
        if (mPipelineRunAllowed && mIsSuppressingPipelineRun) {
            mNotifStabilityManager.invalidateList("pipeline run suppression ended");
@@ -251,7 +259,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
    }

    private boolean isReorderingAllowed() {
        return ((mFullyDozed && mSleepy) || !mPanelExpanded || mCommunalShowing) && !mPulsing;
        final boolean sleepyAndDozed = mFullyDozed && mSleepy;
        final boolean stackShowing = mPanelExpanded || mLockscreenShowing;
        return (sleepyAndDozed || !stackShowing || mCommunalShowing) && !mPulsing;
    }

    /**
@@ -364,4 +374,14 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
        mCommunalShowing = isShowing;
        updateAllowedStates("communalShowing", isShowing);
    }

    private void onLockscreenKeyguardStateTransitionValueChanged(float value) {
        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
            return;
        }

        final boolean isShowing = value > 0.0f;
        mLockscreenShowing = isShowing;
        updateAllowedStates("lockscreenShowing", isShowing);
    }
}
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.systemui.statusbar.notification.collection.coordinator

import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.VisualStabilityLog
import javax.inject.Inject

private const val TAG = "VisualStability"

class VisualStabilityCoordinatorLogger
@Inject
constructor(@VisualStabilityLog private val buffer: LogBuffer) {
    fun logAllowancesChanged(
        wasRunAllowed: Boolean,
        isRunAllowed: Boolean,
        wasReorderingAllowed: Boolean,
        isReorderingAllowed: Boolean,
        field: String,
        value: Boolean
    ) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                bool1 = wasRunAllowed
                bool2 = isRunAllowed
                bool3 = wasReorderingAllowed
                bool4 = isReorderingAllowed
                str1 = field
                str2 = value.toString()
            },
            {
                "stability allowances changed:" +
                    " pipelineRunAllowed $bool1->$bool2" +
                    " reorderingAllowed $bool3->$bool4" +
                    " when setting $str1=$str2"
            }
        )
    }
}