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

Commit f882c667 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[CS] Have NotificationGutsManager listen for shade/LS vis directly.

Don't have CentralSurfaces notify NotificationGutsManager when the
shade or lockscreen is no longer visible and instead have the guts
manager listen for it directly.

Bug: 296050180
Test: verified via logging that #closeAndSaveGuts is invoked at the
same cadence as it previously was with CentralSurfaces
Test: long press on notif, close shade, open shade -> verify guts no
longer showing
Test: atest NotificationGutsManagerTest

Change-Id: Ib20a00ae1686fb1c7d261c3470b8d83218d324dd
parent 07320490
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -114,6 +114,13 @@ public interface NotificationsModule {
    @Binds
    NotifGutsViewManager bindNotifGutsViewManager(NotificationGutsManager notificationGutsManager);

    /** Binds {@link NotificationGutsManager} as a {@link CoreStartable}. */
    @Binds
    @IntoMap
    @ClassKey(NotificationGutsManager.class)
    CoreStartable bindsNotificationGutsManager(NotificationGutsManager notificationGutsManager);


    /** Provides an instance of {@link VisibilityLocationProvider} */
    @Binds
    VisibilityLocationProvider bindVisibilityLocationProvider(
+30 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.notification.ConversationIconFactory;
import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -53,6 +54,7 @@ import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -69,6 +71,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.wmshell.BubblesManager;

import java.util.Optional;
@@ -80,7 +83,7 @@ import javax.inject.Inject;
 * closing guts, and keeping track of the currently exposed notification guts.
 */
@SysUISingleton
public class NotificationGutsManager implements NotifGutsViewManager {
public class NotificationGutsManager implements NotifGutsViewManager, CoreStartable {
    private static final String TAG = "NotificationGutsManager";

    // Must match constant in Settings. Used to highlight preferences when linking to Settings.
@@ -109,6 +112,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {

    private final Handler mMainHandler;
    private final Handler mBgHandler;
    private final JavaAdapter mJavaAdapter;
    private final Optional<BubblesManager> mBubblesManagerOptional;
    private Runnable mOpenRunnable;
    private final INotificationManager mNotificationManager;
@@ -121,6 +125,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
    private final UserContextProvider mContextTracker;
    private final UiEventLogger mUiEventLogger;
    private final ShadeController mShadeController;
    private final WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor;
    private NotifGutsViewListener mGutsListener;
    private final HeadsUpManagerPhone mHeadsUpManagerPhone;
    private final ActivityStarter mActivityStarter;
@@ -129,6 +134,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
    public NotificationGutsManager(Context context,
            @Main Handler mainHandler,
            @Background Handler bgHandler,
            JavaAdapter javaAdapter,
            AccessibilityManager accessibilityManager,
            HighPriorityProvider highPriorityProvider,
            INotificationManager notificationManager,
@@ -143,6 +149,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
            UiEventLogger uiEventLogger,
            OnUserInteractionCallback onUserInteractionCallback,
            ShadeController shadeController,
            WindowRootViewVisibilityInteractor windowRootViewVisibilityInteractor,
            NotificationLockscreenUserManager notificationLockscreenUserManager,
            StatusBarStateController statusBarStateController,
            DeviceProvisionedController deviceProvisionedController,
@@ -152,6 +159,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
        mContext = context;
        mMainHandler = mainHandler;
        mBgHandler = bgHandler;
        mJavaAdapter = javaAdapter;
        mAccessibilityManager = accessibilityManager;
        mHighPriorityProvider = highPriorityProvider;
        mNotificationManager = notificationManager;
@@ -166,6 +174,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
        mUiEventLogger = uiEventLogger;
        mOnUserInteractionCallback = onUserInteractionCallback;
        mShadeController = shadeController;
        mWindowRootViewVisibilityInteractor = windowRootViewVisibilityInteractor;
        mLockscreenUserManager = notificationLockscreenUserManager;
        mStatusBarStateController = statusBarStateController;
        mDeviceProvisionedController = deviceProvisionedController;
@@ -187,6 +196,25 @@ public class NotificationGutsManager implements NotifGutsViewManager {
        mNotificationActivityStarter = notificationActivityStarter;
    }

    @Override
    public void start() {
        mJavaAdapter.alwaysCollectFlow(
                mWindowRootViewVisibilityInteractor.isLockscreenOrShadeVisible(),
                this::onLockscreenShadeVisibilityChanged);
    }

    private void onLockscreenShadeVisibilityChanged(boolean visible) {
        if (!visible) {
            closeAndSaveGuts(
                    /* removeLeavebehind= */ true ,
                    /* force= */ true,
                    /* removeControls= */ true,
                    /* x= */ -1,
                    /* y= */ -1,
                    /* resetMenu= */ true);
        }
    }

    public void onDensityOrFontScaleChanged(NotificationEntry entry) {
        setExposedGuts(entry.getGuts());
        bindGuts(entry.getRow());
@@ -512,7 +540,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
            mNotificationGutsExposed.removeCallbacks(mOpenRunnable);
            mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
        }
        if (resetMenu) {
        if (resetMenu && mListContainer != null) {
            mListContainer.resetExposedMenuView(false /* animate */, true /* force */);
        }
    }
+0 −3
Original line number Diff line number Diff line
@@ -3201,9 +3201,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
            if (visible) {
                DejankUtils.notifyRendererOfExpensiveFrame(
                        getNotificationShadeWindowView(), "onShadeVisibilityChanged");
            } else {
                mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
                        true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
            }
        }
    }
+101 −6
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
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;
@@ -66,11 +67,16 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.internal.statusbar.IStatusBarService;
import com.android.keyguard.TestScopeProvider;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -84,6 +90,9 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager.O
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.wmshell.BubblesManager;

import org.junit.Before;
@@ -97,6 +106,8 @@ import org.mockito.junit.MockitoRule;

import java.util.Optional;

import kotlinx.coroutines.test.TestScope;

/**
 * Tests for {@link NotificationGutsManager}.
 */
@@ -108,6 +119,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {

    private NotificationChannel mTestNotificationChannel = new NotificationChannel(
            TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);

    private TestScope mTestScope = TestScopeProvider.getTestScope();
    private JavaAdapter mJavaAdapter = new JavaAdapter(mTestScope.getBackgroundScope());
    private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
    private TestableLooper mTestableLooper;
    private Handler mHandler;
    private NotificationTestHelper mHelper;
@@ -124,6 +139,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
    @Mock private AccessibilityManager mAccessibilityManager;
    @Mock private HighPriorityProvider mHighPriorityProvider;
    @Mock private INotificationManager mINotificationManager;
    @Mock private IStatusBarService mBarService;
    @Mock private LauncherApps mLauncherApps;
    @Mock private ShortcutManager mShortcutManager;
    @Mock private ChannelEditorDialogController mChannelEditorDialogController;
@@ -140,6 +156,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {

    @Mock private UserManager mUserManager;

    private WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor;

    @Before
    public void setUp() {
        mTestableLooper = TestableLooper.get(this);
@@ -148,21 +166,42 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
        mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
        when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);

        mGutsManager = new NotificationGutsManager(mContext, mHandler, mHandler,
        mWindowRootViewVisibilityInteractor = new WindowRootViewVisibilityInteractor(
                mTestScope.getBackgroundScope(),
                new WindowRootViewVisibilityRepository(mBarService, mExecutor),
                new FakeKeyguardRepository(),
                mHeadsUpManagerPhone);

        mGutsManager = new NotificationGutsManager(
                mContext,
                mHandler,
                mHandler,
                mJavaAdapter,
                mAccessibilityManager,
                mHighPriorityProvider, mINotificationManager, mUserManager,
                mPeopleSpaceWidgetManager, mLauncherApps, mShortcutManager,
                mChannelEditorDialogController, mContextTracker, mAssistantFeedbackController,
                Optional.of(mBubblesManager), new UiEventLoggerFake(), mOnUserInteractionCallback,
                mHighPriorityProvider,
                mINotificationManager,
                mUserManager,
                mPeopleSpaceWidgetManager,
                mLauncherApps,
                mShortcutManager,
                mChannelEditorDialogController,
                mContextTracker,
                mAssistantFeedbackController,
                Optional.of(mBubblesManager),
                new UiEventLoggerFake(),
                mOnUserInteractionCallback,
                mShadeController,
                mWindowRootViewVisibilityInteractor,
                mNotificationLockscreenUserManager,
                mStatusBarStateController,
                mDeviceProvisionedController,
                mMetricsLogger,
                mHeadsUpManagerPhone, mActivityStarter);
                mHeadsUpManagerPhone,
                mActivityStarter);
        mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
                mOnSettingsClickListener);
        mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
        mGutsManager.start();
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -209,6 +248,62 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
        verify(mHeadsUpManagerPhone).setGutsShown(realRow.getEntry(), false);
    }

    @Test
    public void testLockscreenShadeVisible_visible_gutsNotClosed() {
        // First, start out lockscreen or shade as not visible
        mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(false);
        mTestScope.getTestScheduler().runCurrent();

        NotificationGuts guts = mock(NotificationGuts.class);
        mGutsManager.setExposedGuts(guts);

        // WHEN the lockscreen or shade becomes visible
        mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true);
        mTestScope.getTestScheduler().runCurrent();

        // THEN the guts are not closed
        verify(guts, never()).removeCallbacks(any());
        verify(guts, never()).closeControls(
                anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean());
    }

    @Test
    public void testLockscreenShadeVisible_notVisible_gutsClosed() {
        // First, start out lockscreen or shade as visible
        mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true);
        mTestScope.getTestScheduler().runCurrent();

        NotificationGuts guts = mock(NotificationGuts.class);
        mGutsManager.setExposedGuts(guts);

        // WHEN the lockscreen or shade is no longer visible
        mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(false);
        mTestScope.getTestScheduler().runCurrent();

        // THEN the guts are closed
        verify(guts).removeCallbacks(any());
        verify(guts).closeControls(
                /* leavebehinds= */ eq(true),
                /* controls= */ eq(true),
                /* x= */ anyInt(),
                /* y= */ anyInt(),
                /* force= */ eq(true));
    }

    @Test
    public void testLockscreenShadeVisible_notVisible_listContainerReset() {
        // First, start out lockscreen or shade as visible
        mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true);
        mTestScope.getTestScheduler().runCurrent();

        // WHEN the lockscreen or shade is no longer visible
        mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(false);
        mTestScope.getTestScheduler().runCurrent();

        // THEN the list container is reset
        verify(mNotificationListContainer).resetExposedMenuView(anyBoolean(), anyBoolean());
    }

    @Test
    public void testChangeDensityOrFontScale() {
        NotificationGuts guts = spy(new NotificationGuts(mContext));