Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpNotificationIconViewStateRepository.kt 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * 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.data.repository import android.graphics.Rect import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow /** View-states pertaining to heads-up notification icons. */ @SysUISingleton class HeadsUpNotificationIconViewStateRepository @Inject constructor() { /** Notification key for a notification icon to show isolated, or `null` if none. */ val isolatedNotification = MutableStateFlow<String?>(null) /** Area to display the isolated notification, or `null` if none. */ val isolatedIconLocation = MutableStateFlow<Rect?>(null) } packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationIconInteractor.kt 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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.domain.interactor import android.graphics.Rect import com.android.systemui.statusbar.notification.data.repository.HeadsUpNotificationIconViewStateRepository import javax.inject.Inject import kotlinx.coroutines.flow.Flow /** Domain logic pertaining to heads up notification icons. */ class HeadsUpNotificationIconInteractor @Inject constructor( private val repository: HeadsUpNotificationIconViewStateRepository, ) { /** Notification key for a notification icon to show isolated, or `null` if none. */ val isolatedIconLocation: Flow<Rect?> = repository.isolatedIconLocation /** Area to display the isolated notification, or `null` if none. */ val isolatedNotification: Flow<String?> = repository.isolatedNotification /** Updates the location where isolated notification icons are shown. */ fun setIsolatedIconLocation(rect: Rect?) { repository.isolatedIconLocation.value = rect } /** Updates which notification will have its icon displayed isolated. */ fun setIsolatedIconNotificationKey(key: String?) { repository.isolatedNotification.value = key } } packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt +3 −6 Original line number Diff line number Diff line Loading @@ -136,13 +136,10 @@ constructor( override fun updateAodNotificationIcons() = unsupported override fun showIconIsolated(icon: StatusBarIconView?, animated: Boolean) { notificationIcons!!.showIconIsolated(icon, animated) } override fun showIconIsolated(icon: StatusBarIconView?, animated: Boolean) = unsupported override fun setIsolatedIconLocation(iconDrawingRect: Rect, requireStateUpdate: Boolean) { notificationIcons!!.setIsolatedIconLocation(iconDrawingRect, requireStateUpdate) } override fun setIsolatedIconLocation(iconDrawingRect: Rect, requireStateUpdate: Boolean) = unsupported override fun setAnimationsEnabled(enabled: Boolean) = unsupported Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +69 −25 Original line number Diff line number Diff line Loading @@ -77,8 +77,56 @@ object NotificationIconContainerViewBinder { val contrastColorUtil = ContrastColorUtil.getInstance(view.context) return view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } launch { bindAnimationsEnabled(viewModel, view) } launch { bindIsDozing(viewModel, view, dozeParameters) } // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC // view-binder launch { bindVisibility( viewModel, view, configuration, featureFlags, screenOffAnimationController, ) } launch { bindIconColors(viewModel, view, contrastColorUtil) } launch { bindIconViewData( viewModel, view, configuration, configurationController, viewStore, ) } launch { bindIsolatedIcon(viewModel, view, viewStore) } } } } private suspend fun bindAnimationsEnabled( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer ) { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } private suspend fun bindIconColors( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer, contrastColorUtil: ContrastColorUtil, ) { viewModel.iconColors .mapNotNull { lookup -> lookup.iconColors(view.viewBounds) } .collect { iconLookup -> applyTint(view, iconLookup, contrastColorUtil) } } private suspend fun bindIsDozing( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer, dozeParameters: DozeParameters, ) { viewModel.isDozing.collect { isDozing -> if (isDozing.isAnimating) { val animate = !dozeParameters.displayNeedsBlanking Loading @@ -97,30 +145,26 @@ object NotificationIconContainerViewBinder { } } } // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC // view-binder private suspend fun bindIsolatedIcon( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer, viewStore: IconViewStore, ) { coroutineScope { launch { bindVisibility( viewModel, view, configuration, featureFlags, screenOffAnimationController, ) viewModel.isolatedIconLocation.collect { location -> view.setIsolatedIconLocation(location, true) } launch { viewModel.iconColors .mapNotNull { lookup -> lookup.iconColors(view.viewBounds) } .collect { iconLookup -> applyTint(view, iconLookup, contrastColorUtil) } } launch { bindIconViewData( viewModel, view, configuration, configurationController, viewStore, ) viewModel.isolatedIcon.collect { iconInfo -> val iconView = iconInfo.value?.let { viewStore.iconView(it.notifKey) } if (iconInfo.isAnimating) { view.showIconIsolatedAnimated(iconView, iconInfo::stopAnimating) } else { view.showIconIsolated(iconView) } } } } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt +7 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.statusbar.notification.domain.interactor.Notificatio import com.android.systemui.statusbar.notification.icon.domain.interactor.AlwaysOnDisplayNotificationIconsInteractor import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.ColorLookup import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconColors import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconInfo import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconsViewData import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.ScreenOffAnimationController Loading @@ -46,6 +47,8 @@ import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map /** View-model for the row of notification icons displayed on the always-on display. */ Loading Loading @@ -140,6 +143,10 @@ constructor( ) } override val isolatedIcon: Flow<AnimatedValue<IconInfo?>> = flowOf(AnimatedValue.NotAnimating(null)) override val isolatedIconLocation: Flow<Rect> = emptyFlow() /** Is there an expanded pulse, are we animating in response? */ private fun isPulseExpandingAnimated(): Flow<AnimatedValue<Boolean>> { return notificationsKeyguardInteractor.isPulseExpanding Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpNotificationIconViewStateRepository.kt 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * 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.data.repository import android.graphics.Rect import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow /** View-states pertaining to heads-up notification icons. */ @SysUISingleton class HeadsUpNotificationIconViewStateRepository @Inject constructor() { /** Notification key for a notification icon to show isolated, or `null` if none. */ val isolatedNotification = MutableStateFlow<String?>(null) /** Area to display the isolated notification, or `null` if none. */ val isolatedIconLocation = MutableStateFlow<Rect?>(null) }
packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationIconInteractor.kt 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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.domain.interactor import android.graphics.Rect import com.android.systemui.statusbar.notification.data.repository.HeadsUpNotificationIconViewStateRepository import javax.inject.Inject import kotlinx.coroutines.flow.Flow /** Domain logic pertaining to heads up notification icons. */ class HeadsUpNotificationIconInteractor @Inject constructor( private val repository: HeadsUpNotificationIconViewStateRepository, ) { /** Notification key for a notification icon to show isolated, or `null` if none. */ val isolatedIconLocation: Flow<Rect?> = repository.isolatedIconLocation /** Area to display the isolated notification, or `null` if none. */ val isolatedNotification: Flow<String?> = repository.isolatedNotification /** Updates the location where isolated notification icons are shown. */ fun setIsolatedIconLocation(rect: Rect?) { repository.isolatedIconLocation.value = rect } /** Updates which notification will have its icon displayed isolated. */ fun setIsolatedIconNotificationKey(key: String?) { repository.isolatedNotification.value = key } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt +3 −6 Original line number Diff line number Diff line Loading @@ -136,13 +136,10 @@ constructor( override fun updateAodNotificationIcons() = unsupported override fun showIconIsolated(icon: StatusBarIconView?, animated: Boolean) { notificationIcons!!.showIconIsolated(icon, animated) } override fun showIconIsolated(icon: StatusBarIconView?, animated: Boolean) = unsupported override fun setIsolatedIconLocation(iconDrawingRect: Rect, requireStateUpdate: Boolean) { notificationIcons!!.setIsolatedIconLocation(iconDrawingRect, requireStateUpdate) } override fun setIsolatedIconLocation(iconDrawingRect: Rect, requireStateUpdate: Boolean) = unsupported override fun setAnimationsEnabled(enabled: Boolean) = unsupported Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +69 −25 Original line number Diff line number Diff line Loading @@ -77,8 +77,56 @@ object NotificationIconContainerViewBinder { val contrastColorUtil = ContrastColorUtil.getInstance(view.context) return view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } launch { bindAnimationsEnabled(viewModel, view) } launch { bindIsDozing(viewModel, view, dozeParameters) } // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC // view-binder launch { bindVisibility( viewModel, view, configuration, featureFlags, screenOffAnimationController, ) } launch { bindIconColors(viewModel, view, contrastColorUtil) } launch { bindIconViewData( viewModel, view, configuration, configurationController, viewStore, ) } launch { bindIsolatedIcon(viewModel, view, viewStore) } } } } private suspend fun bindAnimationsEnabled( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer ) { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } private suspend fun bindIconColors( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer, contrastColorUtil: ContrastColorUtil, ) { viewModel.iconColors .mapNotNull { lookup -> lookup.iconColors(view.viewBounds) } .collect { iconLookup -> applyTint(view, iconLookup, contrastColorUtil) } } private suspend fun bindIsDozing( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer, dozeParameters: DozeParameters, ) { viewModel.isDozing.collect { isDozing -> if (isDozing.isAnimating) { val animate = !dozeParameters.displayNeedsBlanking Loading @@ -97,30 +145,26 @@ object NotificationIconContainerViewBinder { } } } // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC // view-binder private suspend fun bindIsolatedIcon( viewModel: NotificationIconContainerViewModel, view: NotificationIconContainer, viewStore: IconViewStore, ) { coroutineScope { launch { bindVisibility( viewModel, view, configuration, featureFlags, screenOffAnimationController, ) viewModel.isolatedIconLocation.collect { location -> view.setIsolatedIconLocation(location, true) } launch { viewModel.iconColors .mapNotNull { lookup -> lookup.iconColors(view.viewBounds) } .collect { iconLookup -> applyTint(view, iconLookup, contrastColorUtil) } } launch { bindIconViewData( viewModel, view, configuration, configurationController, viewStore, ) viewModel.isolatedIcon.collect { iconInfo -> val iconView = iconInfo.value?.let { viewStore.iconView(it.notifKey) } if (iconInfo.isAnimating) { view.showIconIsolatedAnimated(iconView, iconInfo::stopAnimating) } else { view.showIconIsolated(iconView) } } } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt +7 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.statusbar.notification.domain.interactor.Notificatio import com.android.systemui.statusbar.notification.icon.domain.interactor.AlwaysOnDisplayNotificationIconsInteractor import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.ColorLookup import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconColors import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconInfo import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconsViewData import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.ScreenOffAnimationController Loading @@ -46,6 +47,8 @@ import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map /** View-model for the row of notification icons displayed on the always-on display. */ Loading Loading @@ -140,6 +143,10 @@ constructor( ) } override val isolatedIcon: Flow<AnimatedValue<IconInfo?>> = flowOf(AnimatedValue.NotAnimating(null)) override val isolatedIconLocation: Flow<Rect> = emptyFlow() /** Is there an expanded pulse, are we animating in response? */ private fun isPulseExpandingAnimated(): Flow<AnimatedValue<Boolean>> { return notificationsKeyguardInteractor.isPulseExpanding Loading