diff options
| author | 2023-08-23 21:04:07 +0000 | |
|---|---|---|
| committer | 2023-08-28 14:03:20 +0000 | |
| commit | f882c6671bff2553257ebfba6ef43e81d416c9e3 (patch) | |
| tree | 8e4911bcb1fc427cf073b49bf57197cc72f3e23b | |
| parent | 073204904c39d0b9aefc1e9c72b2308afeaf0c9c (diff) | |
[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
4 files changed, 138 insertions, 11 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index 12b6e1b6bea5..09be41b56a10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -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( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 6f79ea8c543b..44ead26de012 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -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 */); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 711dae667d76..381c9bbfcd84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -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 */); } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 705d52bcf13f..9e0f83c9fc53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -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(); } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -210,6 +249,62 @@ public class NotificationGutsManagerTest extends SysuiTestCase { } @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)); when(guts.post(any())).thenAnswer(invocation -> { |