diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt index 63cd20bf17caf..26dfe3edf793c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt @@ -50,6 +50,10 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider +import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel +import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerShelfViewModel +import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerStatusBarViewModel +import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.NotificationIconAreaController @@ -60,6 +64,7 @@ import com.android.wm.shell.bubbles.Bubbles import java.util.Optional import java.util.function.Function import javax.inject.Inject +import kotlinx.coroutines.DisposableHandle /** * Controller class for [NotificationIconContainer]. This implementation serves as a temporary @@ -86,6 +91,9 @@ constructor( featureFlags: FeatureFlags, private val statusBarWindowController: StatusBarWindowController, private val screenOffAnimationController: ScreenOffAnimationController, + private val shelfIconsViewModel: NotificationIconContainerShelfViewModel, + private val statusBarIconsViewModel: NotificationIconContainerStatusBarViewModel, + private val aodIconsViewModel: NotificationIconContainerAlwaysOnDisplayViewModel, ) : NotificationIconAreaController, DarkIconDispatcher.DarkReceiver, @@ -106,6 +114,7 @@ constructor( private var notificationIcons: NotificationIconContainer? = null private var shelfIcons: NotificationIconContainer? = null private var aodIcons: NotificationIconContainer? = null + private var aodBindJob: DisposableHandle? = null private var aodIconAppearTranslation = 0 private var animationsEnabled = false private var aodIconTint = 0 @@ -142,9 +151,11 @@ constructor( if (changed) { this.aodIcons!!.setAnimationsEnabled(false) this.aodIcons!!.removeAllViews() + aodBindJob?.dispose() } this.aodIcons = aodIcons this.aodIcons!!.setOnLockScreen(true) + aodBindJob = NotificationIconContainerViewBinder.bind(aodIcons, aodIconsViewModel) updateAodIconsVisibility(animate = false, forceUpdate = changed) updateAnimations() if (changed) { @@ -153,13 +164,12 @@ constructor( updateIconLayoutParams(context) } - override fun setupShelf(notificationShelfController: NotificationShelfController) { - shelfRefactor.assertDisabled() - shelfIcons = notificationShelfController.shelfIcons - } + override fun setupShelf(notificationShelfController: NotificationShelfController) = + NotificationShelfViewBinderWrapperControllerImpl.unsupported override fun setShelfIcons(icons: NotificationIconContainer) { if (shelfRefactor.expectEnabled()) { + NotificationIconContainerViewBinder.bind(icons, shelfIconsViewModel) shelfIcons = icons } } @@ -329,6 +339,7 @@ constructor( val layoutInflater = LayoutInflater.from(context) notificationIconArea = inflateIconArea(layoutInflater) notificationIcons = notificationIconArea?.findViewById(R.id.notificationIcons) + NotificationIconContainerViewBinder.bind(notificationIcons!!, statusBarIconsViewModel) } private fun updateIconLayoutParams(context: Context) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt index d06ff34f8c739..8293bb329a018 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt @@ -20,13 +20,14 @@ import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel import com.android.systemui.statusbar.phone.NotificationIconContainer +import kotlinx.coroutines.DisposableHandle /** Binds a [NotificationIconContainer] to its [view model][NotificationIconContainerViewModel]. */ object NotificationIconContainerViewBinder { fun bind( view: NotificationIconContainer, viewModel: NotificationIconContainerViewModel, - ) { - view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) {} } + ): DisposableHandle { + return view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) {} } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt new file mode 100644 index 0000000000000..f68b0ef796384 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 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.icon.ui.viewmodel + +import javax.inject.Inject + +/** View-model for the row of notification icons displayed on the always-on display. */ +class NotificationIconContainerAlwaysOnDisplayViewModel @Inject constructor() : + NotificationIconContainerViewModel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt new file mode 100644 index 0000000000000..933c76f19aee7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 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.icon.ui.viewmodel + +import javax.inject.Inject + +/** View-model for the overflow row of notification icons displayed in the notification shade. */ +class NotificationIconContainerShelfViewModel @Inject constructor() : + NotificationIconContainerViewModel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt new file mode 100644 index 0000000000000..2217646e60224 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 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.icon.ui.viewmodel + +import javax.inject.Inject + +/** View-model for the row of notification icons displayed in the status bar, */ +class NotificationIconContainerStatusBarViewModel @Inject constructor() : + NotificationIconContainerViewModel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt index 22a87a7c9432c..b92c51fac5f66 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt @@ -64,8 +64,10 @@ class NotificationShelfViewBinderWrapperControllerImpl @Inject constructor() : override fun setOnClickListener(listener: View.OnClickListener) = unsupported - private val unsupported: Nothing - get() = error("Code path not supported when NOTIFICATION_SHELF_REFACTOR is disabled") + companion object { + val unsupported: Nothing + get() = error("Code path not supported when NOTIFICATION_SHELF_REFACTOR is disabled") + } } /** Binds a [NotificationShelf] to its [view model][NotificationShelfViewModel]. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt index d6f685d69c3cd..b8792a8aeacd8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt @@ -27,6 +27,9 @@ import com.android.systemui.statusbar.NotificationListener import com.android.systemui.statusbar.NotificationMediaManager import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider +import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel +import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerShelfViewModel +import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerStatusBarViewModel import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.NotificationIconContainer @@ -35,7 +38,8 @@ import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.mockito.whenever import com.android.wm.shell.bubbles.Bubbles import java.util.Optional -import org.junit.Assert +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -45,7 +49,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) class NotificationIconAreaControllerViewBinderWrapperImplTest : SysuiTestCase() { @Mock private lateinit var notifListener: NotificationListener @Mock private lateinit var statusBarStateController: StatusBarStateController @@ -62,6 +66,10 @@ class NotificationIconAreaControllerViewBinderWrapperImplTest : SysuiTestCase() @Mock private lateinit var aodIcons: NotificationIconContainer @Mock private lateinit var featureFlags: FeatureFlags + private val shelfViewModel = NotificationIconContainerShelfViewModel() + private val statusBarViewModel = NotificationIconContainerStatusBarViewModel() + private val aodViewModel = NotificationIconContainerAlwaysOnDisplayViewModel() + private lateinit var underTest: NotificationIconAreaControllerViewBinderWrapperImpl @Before @@ -82,20 +90,23 @@ class NotificationIconAreaControllerViewBinderWrapperImplTest : SysuiTestCase() darkIconDispatcher, featureFlags, statusBarWindowController, - screenOffAnimController + screenOffAnimController, + shelfViewModel, + statusBarViewModel, + aodViewModel, ) } @Test fun testNotificationIcons_settingHideIcons() { underTest.settingsListener.onStatusBarIconsBehaviorChanged(true) - Assert.assertFalse(underTest.shouldShowLowPriorityIcons()) + assertFalse(underTest.shouldShowLowPriorityIcons()) } @Test fun testNotificationIcons_settingShowIcons() { underTest.settingsListener.onStatusBarIconsBehaviorChanged(false) - Assert.assertTrue(underTest.shouldShowLowPriorityIcons()) + assertTrue(underTest.shouldShowLowPriorityIcons()) } @Test