Loading packages/SystemUI/src/com/android/systemui/Dependency.java +0 −3 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,6 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager.Keyg import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.AutoHideController; Loading Loading @@ -308,7 +307,6 @@ public class Dependency { @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper; @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper; @Inject Lazy<SensorPrivacyController> mSensorPrivacyController; @Inject Lazy<SensorPrivacyController> mSensorPrivacyController; @Inject Lazy<DockManager> mDockManager; @Inject Lazy<DockManager> mDockManager; @Inject Lazy<ChannelEditorDialogController> mChannelEditorDialogController; @Inject Lazy<INotificationManager> mINotificationManager; @Inject Lazy<INotificationManager> mINotificationManager; @Inject Lazy<SysUiState> mSysUiStateFlagsContainer; @Inject Lazy<SysUiState> mSysUiStateFlagsContainer; @Inject Lazy<AlarmManager> mAlarmManager; @Inject Lazy<AlarmManager> mAlarmManager; Loading Loading @@ -498,7 +496,6 @@ public class Dependency { mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get); mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get); mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get); mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get); mProviders.put(DockManager.class, mDockManager::get); mProviders.put(DockManager.class, mDockManager::get); mProviders.put(ChannelEditorDialogController.class, mChannelEditorDialogController::get); mProviders.put(INotificationManager.class, mINotificationManager::get); mProviders.put(INotificationManager.class, mINotificationManager::get); mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get); mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get); mProviders.put(AlarmManager.class, mAlarmManager::get); mProviders.put(AlarmManager.class, mAlarmManager::get); Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger; import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger; import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl; import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl; import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; Loading Loading @@ -109,6 +110,7 @@ public interface NotificationsModule { INotificationManager notificationManager, INotificationManager notificationManager, LauncherApps launcherApps, LauncherApps launcherApps, ShortcutManager shortcutManager, ShortcutManager shortcutManager, ChannelEditorDialogController channelEditorDialogController, CurrentUserContextTracker contextTracker, CurrentUserContextTracker contextTracker, Provider<PriorityOnboardingDialogController.Builder> builderProvider) { Provider<PriorityOnboardingDialogController.Builder> builderProvider) { return new NotificationGutsManager( return new NotificationGutsManager( Loading @@ -121,6 +123,7 @@ public interface NotificationsModule { notificationManager, notificationManager, launcherApps, launcherApps, shortcutManager, shortcutManager, channelEditorDialogController, contextTracker, contextTracker, builderProvider); builderProvider); } } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt +86 −24 Original line number Original line Diff line number Diff line Loading @@ -22,8 +22,8 @@ import android.app.NotificationChannel import android.app.NotificationChannel.DEFAULT_CHANNEL_ID import android.app.NotificationChannel.DEFAULT_CHANNEL_ID import android.app.NotificationChannelGroup import android.app.NotificationChannelGroup import android.app.NotificationManager.IMPORTANCE_NONE import android.app.NotificationManager.IMPORTANCE_NONE import android.app.NotificationManager.Importance import android.content.Context import android.content.Context import android.content.DialogInterface import android.graphics.Color import android.graphics.Color import android.graphics.PixelFormat import android.graphics.PixelFormat import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable Loading @@ -37,8 +37,10 @@ import android.view.Window import android.view.WindowInsets.Type.statusBars import android.view.WindowInsets.Type.statusBars import android.view.WindowManager import android.view.WindowManager import android.widget.TextView import android.widget.TextView import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R import com.android.systemui.R import javax.inject.Inject import javax.inject.Inject import javax.inject.Singleton import javax.inject.Singleton Loading @@ -59,11 +61,13 @@ private const val TAG = "ChannelDialogController" @Singleton @Singleton class ChannelEditorDialogController @Inject constructor( class ChannelEditorDialogController @Inject constructor( c: Context, c: Context, private val noMan: INotificationManager private val noMan: INotificationManager, private val dialogBuilder: ChannelEditorDialog.Builder ) { ) { val context: Context = c.applicationContext val context: Context = c.applicationContext lateinit var dialog: Dialog private var prepared = false private lateinit var dialog: ChannelEditorDialog private var appIcon: Drawable? = null private var appIcon: Drawable? = null private var appUid: Int? = null private var appUid: Int? = null Loading @@ -74,13 +78,16 @@ class ChannelEditorDialogController @Inject constructor( // Caller should set this if they care about when we dismiss // Caller should set this if they care about when we dismiss var onFinishListener: OnChannelEditorDialogFinishedListener? = null var onFinishListener: OnChannelEditorDialogFinishedListener? = null // Channels handed to us from NotificationInfo @VisibleForTesting @VisibleForTesting internal val providedChannels = mutableListOf<NotificationChannel>() internal val paddedChannels = mutableListOf<NotificationChannel>() // Channels handed to us from NotificationInfo private val providedChannels = mutableListOf<NotificationChannel>() // Map from NotificationChannel to importance // Map from NotificationChannel to importance private val edits = mutableMapOf<NotificationChannel, Int>() private val edits = mutableMapOf<NotificationChannel, Int>() var appNotificationsEnabled = true private var appNotificationsEnabled = true // System settings for app notifications private var appNotificationsCurrentlyEnabled: Boolean? = null // Keep a mapping of NotificationChannel.getGroup() to the actual group name for display // Keep a mapping of NotificationChannel.getGroup() to the actual group name for display @VisibleForTesting @VisibleForTesting Loading @@ -106,10 +113,18 @@ class ChannelEditorDialogController @Inject constructor( this.appNotificationsEnabled = checkAreAppNotificationsOn() this.appNotificationsEnabled = checkAreAppNotificationsOn() this.onSettingsClickListener = onSettingsClickListener this.onSettingsClickListener = onSettingsClickListener // These will always start out the same appNotificationsCurrentlyEnabled = appNotificationsEnabled channelGroupList.clear() channelGroupList.clear() channelGroupList.addAll(fetchNotificationChannelGroups()) channelGroupList.addAll(fetchNotificationChannelGroups()) buildGroupNameLookup() buildGroupNameLookup() providedChannels.clear() providedChannels.addAll(channels) padToFourChannels(channels) padToFourChannels(channels) initDialog() prepared = true } } private fun buildGroupNameLookup() { private fun buildGroupNameLookup() { Loading @@ -121,21 +136,21 @@ class ChannelEditorDialogController @Inject constructor( } } private fun padToFourChannels(channels: Set<NotificationChannel>) { private fun padToFourChannels(channels: Set<NotificationChannel>) { providedChannels.clear() paddedChannels.clear() // First, add all of the given channels // First, add all of the given channels providedChannels.addAll(channels.asSequence().take(4)) paddedChannels.addAll(channels.asSequence().take(4)) // Then pad to 4 if we haven't been given that many // Then pad to 4 if we haven't been given that many providedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence()) paddedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence()) .filterNot { providedChannels.contains(it) } .filterNot { paddedChannels.contains(it) } .distinct() .distinct() .take(4 - providedChannels.size)) .take(4 - paddedChannels.size)) // If we only got one channel and it has the default miscellaneous tag, then we actually // If we only got one channel and it has the default miscellaneous tag, then we actually // are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the // are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the // channel // channel if (providedChannels.size == 1 && DEFAULT_CHANNEL_ID == providedChannels[0].id) { if (paddedChannels.size == 1 && DEFAULT_CHANNEL_ID == paddedChannels[0].id) { providedChannels.clear() paddedChannels.clear() } } } } Loading @@ -157,7 +172,9 @@ class ChannelEditorDialogController @Inject constructor( } } fun show() { fun show() { initDialog() if (!prepared) { throw IllegalStateException("Must call prepareDialogForApp() before calling show()") } dialog.show() dialog.show() } } Loading @@ -178,8 +195,10 @@ class ChannelEditorDialogController @Inject constructor( appUid = null appUid = null packageName = null packageName = null appName = null appName = null appNotificationsCurrentlyEnabled = null edits.clear() edits.clear() paddedChannels.clear() providedChannels.clear() providedChannels.clear() groupNameLookup.clear() groupNameLookup.clear() } } Loading @@ -188,12 +207,27 @@ class ChannelEditorDialogController @Inject constructor( return groupNameLookup[groupId] ?: "" return groupNameLookup[groupId] ?: "" } } fun proposeEditForChannel(channel: NotificationChannel, edit: Int) { fun proposeEditForChannel(channel: NotificationChannel, @Importance edit: Int) { if (channel.importance == edit) { if (channel.importance == edit) { edits.remove(channel) edits.remove(channel) } else { } else { edits[channel] = edit edits[channel] = edit } } dialog.updateDoneButtonText(hasChanges()) } fun proposeSetAppNotificationsEnabled(enabled: Boolean) { appNotificationsEnabled = enabled dialog.updateDoneButtonText(hasChanges()) } fun areAppNotificationsEnabled(): Boolean { return appNotificationsEnabled } private fun hasChanges(): Boolean { return edits.isNotEmpty() || (appNotificationsEnabled != appNotificationsCurrentlyEnabled) } } @Suppress("unchecked_cast") @Suppress("unchecked_cast") Loading Loading @@ -241,7 +275,7 @@ class ChannelEditorDialogController @Inject constructor( } } } } if (appNotificationsEnabled != checkAreAppNotificationsOn()) { if (appNotificationsEnabled != appNotificationsCurrentlyEnabled) { applyAppNotificationsOn(appNotificationsEnabled) applyAppNotificationsOn(appNotificationsEnabled) } } } } Loading @@ -252,7 +286,8 @@ class ChannelEditorDialogController @Inject constructor( } } private fun initDialog() { private fun initDialog() { dialog = Dialog(context) dialogBuilder.setContext(context) dialog = dialogBuilder.build() dialog.window?.requestFeature(Window.FEATURE_NO_TITLE) dialog.window?.requestFeature(Window.FEATURE_NO_TITLE) // Prevent a11y readers from reading the first element in the dialog twice // Prevent a11y readers from reading the first element in the dialog twice Loading @@ -260,16 +295,21 @@ class ChannelEditorDialogController @Inject constructor( dialog.apply { dialog.apply { setContentView(R.layout.notif_half_shelf) setContentView(R.layout.notif_half_shelf) setCanceledOnTouchOutside(true) setCanceledOnTouchOutside(true) setOnDismissListener(object : DialogInterface.OnDismissListener { setOnDismissListener { onFinishListener?.onChannelEditorDialogFinished() } override fun onDismiss(dialog: DialogInterface?) { onFinishListener?.onChannelEditorDialogFinished() val listView = findViewById<ChannelEditorListView>(R.id.half_shelf_container) } listView?.apply { }) findViewById<ChannelEditorListView>(R.id.half_shelf_container).apply { controller = this@ChannelEditorDialogController controller = this@ChannelEditorDialogController appIcon = this@ChannelEditorDialogController.appIcon appIcon = this@ChannelEditorDialogController.appIcon appName = this@ChannelEditorDialogController.appName appName = this@ChannelEditorDialogController.appName channels = providedChannels channels = paddedChannels } setOnShowListener { // play a highlight animation for the given channels for (channel in providedChannels) { listView?.highlightChannel(channel) } } } findViewById<TextView>(R.id.done_button)?.setOnClickListener { findViewById<TextView>(R.id.done_button)?.setOnClickListener { Loading Loading @@ -306,6 +346,28 @@ class ChannelEditorDialogController @Inject constructor( or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) } } class ChannelEditorDialog(context: Context) : Dialog(context) { fun updateDoneButtonText(hasChanges: Boolean) { findViewById<TextView>(R.id.done_button)?.setText( if (hasChanges) R.string.inline_ok_button else R.string.inline_done_button) } class Builder @Inject constructor() { private lateinit var context: Context fun setContext(context: Context): Builder { this.context = context return this } fun build(): ChannelEditorDialog { return ChannelEditorDialog(context) } } } interface OnChannelEditorDialogFinishedListener { interface OnChannelEditorDialogFinishedListener { fun onChannelEditorDialogFinished() fun onChannelEditorDialogFinished() } } packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt +48 −8 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.row package com.android.systemui.statusbar.notification.row import android.animation.ArgbEvaluator import android.animation.ValueAnimator import android.app.NotificationChannel import android.app.NotificationChannel import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_NONE import android.app.NotificationManager.IMPORTANCE_NONE Loading @@ -33,8 +35,10 @@ import android.widget.ImageView import android.widget.LinearLayout import android.widget.LinearLayout import android.widget.Switch import android.widget.Switch import android.widget.TextView import android.widget.TextView import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.R import com.android.systemui.util.Assert /** /** * Half-shelf for notification channel controls * Half-shelf for notification channel controls Loading @@ -51,6 +55,7 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a // The first row is for the entire app // The first row is for the entire app private lateinit var appControlRow: AppControlView private lateinit var appControlRow: AppControlView private val channelRows = mutableListOf<ChannelRow>() override fun onFinishInflate() { override fun onFinishInflate() { super.onFinishInflate() super.onFinishInflate() Loading @@ -58,8 +63,21 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a appControlRow = findViewById(R.id.app_control) appControlRow = findViewById(R.id.app_control) } } /** * Play a highlight animation for the given channel (it really should exist but this will just * fail silently if it doesn't) */ fun highlightChannel(channel: NotificationChannel) { Assert.isMainThread() for (row in channelRows) { if (row.channel == channel) { row.playHighlight() } } } private fun updateRows() { private fun updateRows() { val enabled = controller.appNotificationsEnabled val enabled = controller.areAppNotificationsEnabled() val transition = AutoTransition() val transition = AutoTransition() transition.duration = 200 transition.duration = 200 Loading @@ -83,13 +101,10 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a TransitionManager.beginDelayedTransition(this, transition) TransitionManager.beginDelayedTransition(this, transition) // Remove any rows // Remove any rows val n = childCount for (row in channelRows) { for (i in n.downTo(0)) { removeView(row) val child = getChildAt(i) if (child is ChannelRow) { removeView(child) } } } channelRows.clear() updateAppControlRow(enabled) updateAppControlRow(enabled) Loading @@ -105,6 +120,8 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow row.controller = controller row.controller = controller row.channel = channel row.channel = channel channelRows.add(row) addView(row) addView(row) } } Loading @@ -114,7 +131,7 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a .getString(R.string.notification_channel_dialog_title, appName) .getString(R.string.notification_channel_dialog_title, appName) appControlRow.switch.isChecked = enabled appControlRow.switch.isChecked = enabled appControlRow.switch.setOnCheckedChangeListener { _, b -> appControlRow.switch.setOnCheckedChangeListener { _, b -> controller.appNotificationsEnabled = b controller.proposeSetAppNotificationsEnabled(b) updateRows() updateRows() } } } } Loading @@ -140,8 +157,14 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { private lateinit var channelName: TextView private lateinit var channelName: TextView private lateinit var channelDescription: TextView private lateinit var channelDescription: TextView private lateinit var switch: Switch private lateinit var switch: Switch private val highlightColor: Int var gentle = false var gentle = false init { highlightColor = Utils.getColorAttrDefaultColor( context, android.R.attr.colorControlHighlight) } var channel: NotificationChannel? = null var channel: NotificationChannel? = null set(newValue) { set(newValue) { field = newValue field = newValue Loading @@ -150,6 +173,7 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { } } override fun onFinishInflate() { override fun onFinishInflate() { super.onFinishInflate() channelName = findViewById(R.id.channel_name) channelName = findViewById(R.id.channel_name) channelDescription = findViewById(R.id.channel_description) channelDescription = findViewById(R.id.channel_description) switch = findViewById(R.id.toggle) switch = findViewById(R.id.toggle) Loading @@ -161,6 +185,22 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { setOnClickListener { switch.toggle() } setOnClickListener { switch.toggle() } } } /** * Play an animation that highlights this row */ fun playHighlight() { // Use 0 for the start value because our background is given to us by our parent val fadeInLoop = ValueAnimator.ofObject(ArgbEvaluator(), 0, highlightColor) fadeInLoop.duration = 200L fadeInLoop.addUpdateListener { animator -> setBackgroundColor(animator.animatedValue as Int) } fadeInLoop.repeatMode = ValueAnimator.REVERSE // Repeat an odd number of times to we end up normal fadeInLoop.repeatCount = 5 fadeInLoop.start() } private fun updateViews() { private fun updateViews() { val nc = channel ?: return val nc = channel ?: return Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -87,6 +87,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx private final VisualStabilityManager mVisualStabilityManager; private final VisualStabilityManager mVisualStabilityManager; private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager mAccessibilityManager; private final HighPriorityProvider mHighPriorityProvider; private final HighPriorityProvider mHighPriorityProvider; private final ChannelEditorDialogController mChannelEditorDialogController; // Dependencies: // Dependencies: private final NotificationLockscreenUserManager mLockscreenUserManager = private final NotificationLockscreenUserManager mLockscreenUserManager = Loading Loading @@ -127,6 +128,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx INotificationManager notificationManager, INotificationManager notificationManager, LauncherApps launcherApps, LauncherApps launcherApps, ShortcutManager shortcutManager, ShortcutManager shortcutManager, ChannelEditorDialogController channelEditorDialogController, CurrentUserContextTracker contextTracker, CurrentUserContextTracker contextTracker, Provider<PriorityOnboardingDialogController.Builder> builderProvider) { Provider<PriorityOnboardingDialogController.Builder> builderProvider) { mContext = context; mContext = context; Loading @@ -140,6 +142,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mShortcutManager = shortcutManager; mShortcutManager = shortcutManager; mContextTracker = contextTracker; mContextTracker = contextTracker; mBuilderProvider = builderProvider; mBuilderProvider = builderProvider; mChannelEditorDialogController = channelEditorDialogController; } } public void setUpWithPresenter(NotificationPresenter presenter, public void setUpWithPresenter(NotificationPresenter presenter, Loading Loading @@ -348,6 +351,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx pmUser, pmUser, mNotificationManager, mNotificationManager, mVisualStabilityManager, mVisualStabilityManager, mChannelEditorDialogController, packageName, packageName, row.getEntry().getChannel(), row.getEntry().getChannel(), row.getUniqueChannels(), row.getUniqueChannels(), Loading Loading @@ -390,6 +394,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx notificationInfoView.bindNotification( notificationInfoView.bindNotification( pmUser, pmUser, mNotificationManager, mNotificationManager, mChannelEditorDialogController, packageName, packageName, row.getEntry().getChannel(), row.getEntry().getChannel(), row.getUniqueChannels(), row.getUniqueChannels(), Loading Loading
packages/SystemUI/src/com/android/systemui/Dependency.java +0 −3 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,6 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager.Keyg import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.AutoHideController; Loading Loading @@ -308,7 +307,6 @@ public class Dependency { @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper; @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper; @Inject Lazy<SensorPrivacyController> mSensorPrivacyController; @Inject Lazy<SensorPrivacyController> mSensorPrivacyController; @Inject Lazy<DockManager> mDockManager; @Inject Lazy<DockManager> mDockManager; @Inject Lazy<ChannelEditorDialogController> mChannelEditorDialogController; @Inject Lazy<INotificationManager> mINotificationManager; @Inject Lazy<INotificationManager> mINotificationManager; @Inject Lazy<SysUiState> mSysUiStateFlagsContainer; @Inject Lazy<SysUiState> mSysUiStateFlagsContainer; @Inject Lazy<AlarmManager> mAlarmManager; @Inject Lazy<AlarmManager> mAlarmManager; Loading Loading @@ -498,7 +496,6 @@ public class Dependency { mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get); mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get); mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get); mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get); mProviders.put(DockManager.class, mDockManager::get); mProviders.put(DockManager.class, mDockManager::get); mProviders.put(ChannelEditorDialogController.class, mChannelEditorDialogController::get); mProviders.put(INotificationManager.class, mINotificationManager::get); mProviders.put(INotificationManager.class, mINotificationManager::get); mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get); mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get); mProviders.put(AlarmManager.class, mAlarmManager::get); mProviders.put(AlarmManager.class, mAlarmManager::get); Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger; import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger; import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl; import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl; import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; Loading Loading @@ -109,6 +110,7 @@ public interface NotificationsModule { INotificationManager notificationManager, INotificationManager notificationManager, LauncherApps launcherApps, LauncherApps launcherApps, ShortcutManager shortcutManager, ShortcutManager shortcutManager, ChannelEditorDialogController channelEditorDialogController, CurrentUserContextTracker contextTracker, CurrentUserContextTracker contextTracker, Provider<PriorityOnboardingDialogController.Builder> builderProvider) { Provider<PriorityOnboardingDialogController.Builder> builderProvider) { return new NotificationGutsManager( return new NotificationGutsManager( Loading @@ -121,6 +123,7 @@ public interface NotificationsModule { notificationManager, notificationManager, launcherApps, launcherApps, shortcutManager, shortcutManager, channelEditorDialogController, contextTracker, contextTracker, builderProvider); builderProvider); } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt +86 −24 Original line number Original line Diff line number Diff line Loading @@ -22,8 +22,8 @@ import android.app.NotificationChannel import android.app.NotificationChannel.DEFAULT_CHANNEL_ID import android.app.NotificationChannel.DEFAULT_CHANNEL_ID import android.app.NotificationChannelGroup import android.app.NotificationChannelGroup import android.app.NotificationManager.IMPORTANCE_NONE import android.app.NotificationManager.IMPORTANCE_NONE import android.app.NotificationManager.Importance import android.content.Context import android.content.Context import android.content.DialogInterface import android.graphics.Color import android.graphics.Color import android.graphics.PixelFormat import android.graphics.PixelFormat import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable Loading @@ -37,8 +37,10 @@ import android.view.Window import android.view.WindowInsets.Type.statusBars import android.view.WindowInsets.Type.statusBars import android.view.WindowManager import android.view.WindowManager import android.widget.TextView import android.widget.TextView import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R import com.android.systemui.R import javax.inject.Inject import javax.inject.Inject import javax.inject.Singleton import javax.inject.Singleton Loading @@ -59,11 +61,13 @@ private const val TAG = "ChannelDialogController" @Singleton @Singleton class ChannelEditorDialogController @Inject constructor( class ChannelEditorDialogController @Inject constructor( c: Context, c: Context, private val noMan: INotificationManager private val noMan: INotificationManager, private val dialogBuilder: ChannelEditorDialog.Builder ) { ) { val context: Context = c.applicationContext val context: Context = c.applicationContext lateinit var dialog: Dialog private var prepared = false private lateinit var dialog: ChannelEditorDialog private var appIcon: Drawable? = null private var appIcon: Drawable? = null private var appUid: Int? = null private var appUid: Int? = null Loading @@ -74,13 +78,16 @@ class ChannelEditorDialogController @Inject constructor( // Caller should set this if they care about when we dismiss // Caller should set this if they care about when we dismiss var onFinishListener: OnChannelEditorDialogFinishedListener? = null var onFinishListener: OnChannelEditorDialogFinishedListener? = null // Channels handed to us from NotificationInfo @VisibleForTesting @VisibleForTesting internal val providedChannels = mutableListOf<NotificationChannel>() internal val paddedChannels = mutableListOf<NotificationChannel>() // Channels handed to us from NotificationInfo private val providedChannels = mutableListOf<NotificationChannel>() // Map from NotificationChannel to importance // Map from NotificationChannel to importance private val edits = mutableMapOf<NotificationChannel, Int>() private val edits = mutableMapOf<NotificationChannel, Int>() var appNotificationsEnabled = true private var appNotificationsEnabled = true // System settings for app notifications private var appNotificationsCurrentlyEnabled: Boolean? = null // Keep a mapping of NotificationChannel.getGroup() to the actual group name for display // Keep a mapping of NotificationChannel.getGroup() to the actual group name for display @VisibleForTesting @VisibleForTesting Loading @@ -106,10 +113,18 @@ class ChannelEditorDialogController @Inject constructor( this.appNotificationsEnabled = checkAreAppNotificationsOn() this.appNotificationsEnabled = checkAreAppNotificationsOn() this.onSettingsClickListener = onSettingsClickListener this.onSettingsClickListener = onSettingsClickListener // These will always start out the same appNotificationsCurrentlyEnabled = appNotificationsEnabled channelGroupList.clear() channelGroupList.clear() channelGroupList.addAll(fetchNotificationChannelGroups()) channelGroupList.addAll(fetchNotificationChannelGroups()) buildGroupNameLookup() buildGroupNameLookup() providedChannels.clear() providedChannels.addAll(channels) padToFourChannels(channels) padToFourChannels(channels) initDialog() prepared = true } } private fun buildGroupNameLookup() { private fun buildGroupNameLookup() { Loading @@ -121,21 +136,21 @@ class ChannelEditorDialogController @Inject constructor( } } private fun padToFourChannels(channels: Set<NotificationChannel>) { private fun padToFourChannels(channels: Set<NotificationChannel>) { providedChannels.clear() paddedChannels.clear() // First, add all of the given channels // First, add all of the given channels providedChannels.addAll(channels.asSequence().take(4)) paddedChannels.addAll(channels.asSequence().take(4)) // Then pad to 4 if we haven't been given that many // Then pad to 4 if we haven't been given that many providedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence()) paddedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence()) .filterNot { providedChannels.contains(it) } .filterNot { paddedChannels.contains(it) } .distinct() .distinct() .take(4 - providedChannels.size)) .take(4 - paddedChannels.size)) // If we only got one channel and it has the default miscellaneous tag, then we actually // If we only got one channel and it has the default miscellaneous tag, then we actually // are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the // are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the // channel // channel if (providedChannels.size == 1 && DEFAULT_CHANNEL_ID == providedChannels[0].id) { if (paddedChannels.size == 1 && DEFAULT_CHANNEL_ID == paddedChannels[0].id) { providedChannels.clear() paddedChannels.clear() } } } } Loading @@ -157,7 +172,9 @@ class ChannelEditorDialogController @Inject constructor( } } fun show() { fun show() { initDialog() if (!prepared) { throw IllegalStateException("Must call prepareDialogForApp() before calling show()") } dialog.show() dialog.show() } } Loading @@ -178,8 +195,10 @@ class ChannelEditorDialogController @Inject constructor( appUid = null appUid = null packageName = null packageName = null appName = null appName = null appNotificationsCurrentlyEnabled = null edits.clear() edits.clear() paddedChannels.clear() providedChannels.clear() providedChannels.clear() groupNameLookup.clear() groupNameLookup.clear() } } Loading @@ -188,12 +207,27 @@ class ChannelEditorDialogController @Inject constructor( return groupNameLookup[groupId] ?: "" return groupNameLookup[groupId] ?: "" } } fun proposeEditForChannel(channel: NotificationChannel, edit: Int) { fun proposeEditForChannel(channel: NotificationChannel, @Importance edit: Int) { if (channel.importance == edit) { if (channel.importance == edit) { edits.remove(channel) edits.remove(channel) } else { } else { edits[channel] = edit edits[channel] = edit } } dialog.updateDoneButtonText(hasChanges()) } fun proposeSetAppNotificationsEnabled(enabled: Boolean) { appNotificationsEnabled = enabled dialog.updateDoneButtonText(hasChanges()) } fun areAppNotificationsEnabled(): Boolean { return appNotificationsEnabled } private fun hasChanges(): Boolean { return edits.isNotEmpty() || (appNotificationsEnabled != appNotificationsCurrentlyEnabled) } } @Suppress("unchecked_cast") @Suppress("unchecked_cast") Loading Loading @@ -241,7 +275,7 @@ class ChannelEditorDialogController @Inject constructor( } } } } if (appNotificationsEnabled != checkAreAppNotificationsOn()) { if (appNotificationsEnabled != appNotificationsCurrentlyEnabled) { applyAppNotificationsOn(appNotificationsEnabled) applyAppNotificationsOn(appNotificationsEnabled) } } } } Loading @@ -252,7 +286,8 @@ class ChannelEditorDialogController @Inject constructor( } } private fun initDialog() { private fun initDialog() { dialog = Dialog(context) dialogBuilder.setContext(context) dialog = dialogBuilder.build() dialog.window?.requestFeature(Window.FEATURE_NO_TITLE) dialog.window?.requestFeature(Window.FEATURE_NO_TITLE) // Prevent a11y readers from reading the first element in the dialog twice // Prevent a11y readers from reading the first element in the dialog twice Loading @@ -260,16 +295,21 @@ class ChannelEditorDialogController @Inject constructor( dialog.apply { dialog.apply { setContentView(R.layout.notif_half_shelf) setContentView(R.layout.notif_half_shelf) setCanceledOnTouchOutside(true) setCanceledOnTouchOutside(true) setOnDismissListener(object : DialogInterface.OnDismissListener { setOnDismissListener { onFinishListener?.onChannelEditorDialogFinished() } override fun onDismiss(dialog: DialogInterface?) { onFinishListener?.onChannelEditorDialogFinished() val listView = findViewById<ChannelEditorListView>(R.id.half_shelf_container) } listView?.apply { }) findViewById<ChannelEditorListView>(R.id.half_shelf_container).apply { controller = this@ChannelEditorDialogController controller = this@ChannelEditorDialogController appIcon = this@ChannelEditorDialogController.appIcon appIcon = this@ChannelEditorDialogController.appIcon appName = this@ChannelEditorDialogController.appName appName = this@ChannelEditorDialogController.appName channels = providedChannels channels = paddedChannels } setOnShowListener { // play a highlight animation for the given channels for (channel in providedChannels) { listView?.highlightChannel(channel) } } } findViewById<TextView>(R.id.done_button)?.setOnClickListener { findViewById<TextView>(R.id.done_button)?.setOnClickListener { Loading Loading @@ -306,6 +346,28 @@ class ChannelEditorDialogController @Inject constructor( or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) } } class ChannelEditorDialog(context: Context) : Dialog(context) { fun updateDoneButtonText(hasChanges: Boolean) { findViewById<TextView>(R.id.done_button)?.setText( if (hasChanges) R.string.inline_ok_button else R.string.inline_done_button) } class Builder @Inject constructor() { private lateinit var context: Context fun setContext(context: Context): Builder { this.context = context return this } fun build(): ChannelEditorDialog { return ChannelEditorDialog(context) } } } interface OnChannelEditorDialogFinishedListener { interface OnChannelEditorDialogFinishedListener { fun onChannelEditorDialogFinished() fun onChannelEditorDialogFinished() } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt +48 −8 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.row package com.android.systemui.statusbar.notification.row import android.animation.ArgbEvaluator import android.animation.ValueAnimator import android.app.NotificationChannel import android.app.NotificationChannel import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_NONE import android.app.NotificationManager.IMPORTANCE_NONE Loading @@ -33,8 +35,10 @@ import android.widget.ImageView import android.widget.LinearLayout import android.widget.LinearLayout import android.widget.Switch import android.widget.Switch import android.widget.TextView import android.widget.TextView import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.R import com.android.systemui.util.Assert /** /** * Half-shelf for notification channel controls * Half-shelf for notification channel controls Loading @@ -51,6 +55,7 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a // The first row is for the entire app // The first row is for the entire app private lateinit var appControlRow: AppControlView private lateinit var appControlRow: AppControlView private val channelRows = mutableListOf<ChannelRow>() override fun onFinishInflate() { override fun onFinishInflate() { super.onFinishInflate() super.onFinishInflate() Loading @@ -58,8 +63,21 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a appControlRow = findViewById(R.id.app_control) appControlRow = findViewById(R.id.app_control) } } /** * Play a highlight animation for the given channel (it really should exist but this will just * fail silently if it doesn't) */ fun highlightChannel(channel: NotificationChannel) { Assert.isMainThread() for (row in channelRows) { if (row.channel == channel) { row.playHighlight() } } } private fun updateRows() { private fun updateRows() { val enabled = controller.appNotificationsEnabled val enabled = controller.areAppNotificationsEnabled() val transition = AutoTransition() val transition = AutoTransition() transition.duration = 200 transition.duration = 200 Loading @@ -83,13 +101,10 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a TransitionManager.beginDelayedTransition(this, transition) TransitionManager.beginDelayedTransition(this, transition) // Remove any rows // Remove any rows val n = childCount for (row in channelRows) { for (i in n.downTo(0)) { removeView(row) val child = getChildAt(i) if (child is ChannelRow) { removeView(child) } } } channelRows.clear() updateAppControlRow(enabled) updateAppControlRow(enabled) Loading @@ -105,6 +120,8 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow row.controller = controller row.controller = controller row.channel = channel row.channel = channel channelRows.add(row) addView(row) addView(row) } } Loading @@ -114,7 +131,7 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a .getString(R.string.notification_channel_dialog_title, appName) .getString(R.string.notification_channel_dialog_title, appName) appControlRow.switch.isChecked = enabled appControlRow.switch.isChecked = enabled appControlRow.switch.setOnCheckedChangeListener { _, b -> appControlRow.switch.setOnCheckedChangeListener { _, b -> controller.appNotificationsEnabled = b controller.proposeSetAppNotificationsEnabled(b) updateRows() updateRows() } } } } Loading @@ -140,8 +157,14 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { private lateinit var channelName: TextView private lateinit var channelName: TextView private lateinit var channelDescription: TextView private lateinit var channelDescription: TextView private lateinit var switch: Switch private lateinit var switch: Switch private val highlightColor: Int var gentle = false var gentle = false init { highlightColor = Utils.getColorAttrDefaultColor( context, android.R.attr.colorControlHighlight) } var channel: NotificationChannel? = null var channel: NotificationChannel? = null set(newValue) { set(newValue) { field = newValue field = newValue Loading @@ -150,6 +173,7 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { } } override fun onFinishInflate() { override fun onFinishInflate() { super.onFinishInflate() channelName = findViewById(R.id.channel_name) channelName = findViewById(R.id.channel_name) channelDescription = findViewById(R.id.channel_description) channelDescription = findViewById(R.id.channel_description) switch = findViewById(R.id.toggle) switch = findViewById(R.id.toggle) Loading @@ -161,6 +185,22 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { setOnClickListener { switch.toggle() } setOnClickListener { switch.toggle() } } } /** * Play an animation that highlights this row */ fun playHighlight() { // Use 0 for the start value because our background is given to us by our parent val fadeInLoop = ValueAnimator.ofObject(ArgbEvaluator(), 0, highlightColor) fadeInLoop.duration = 200L fadeInLoop.addUpdateListener { animator -> setBackgroundColor(animator.animatedValue as Int) } fadeInLoop.repeatMode = ValueAnimator.REVERSE // Repeat an odd number of times to we end up normal fadeInLoop.repeatCount = 5 fadeInLoop.start() } private fun updateViews() { private fun updateViews() { val nc = channel ?: return val nc = channel ?: return Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -87,6 +87,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx private final VisualStabilityManager mVisualStabilityManager; private final VisualStabilityManager mVisualStabilityManager; private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager mAccessibilityManager; private final HighPriorityProvider mHighPriorityProvider; private final HighPriorityProvider mHighPriorityProvider; private final ChannelEditorDialogController mChannelEditorDialogController; // Dependencies: // Dependencies: private final NotificationLockscreenUserManager mLockscreenUserManager = private final NotificationLockscreenUserManager mLockscreenUserManager = Loading Loading @@ -127,6 +128,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx INotificationManager notificationManager, INotificationManager notificationManager, LauncherApps launcherApps, LauncherApps launcherApps, ShortcutManager shortcutManager, ShortcutManager shortcutManager, ChannelEditorDialogController channelEditorDialogController, CurrentUserContextTracker contextTracker, CurrentUserContextTracker contextTracker, Provider<PriorityOnboardingDialogController.Builder> builderProvider) { Provider<PriorityOnboardingDialogController.Builder> builderProvider) { mContext = context; mContext = context; Loading @@ -140,6 +142,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mShortcutManager = shortcutManager; mShortcutManager = shortcutManager; mContextTracker = contextTracker; mContextTracker = contextTracker; mBuilderProvider = builderProvider; mBuilderProvider = builderProvider; mChannelEditorDialogController = channelEditorDialogController; } } public void setUpWithPresenter(NotificationPresenter presenter, public void setUpWithPresenter(NotificationPresenter presenter, Loading Loading @@ -348,6 +351,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx pmUser, pmUser, mNotificationManager, mNotificationManager, mVisualStabilityManager, mVisualStabilityManager, mChannelEditorDialogController, packageName, packageName, row.getEntry().getChannel(), row.getEntry().getChannel(), row.getUniqueChannels(), row.getUniqueChannels(), Loading Loading @@ -390,6 +394,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx notificationInfoView.bindNotification( notificationInfoView.bindNotification( pmUser, pmUser, mNotificationManager, mNotificationManager, mChannelEditorDialogController, packageName, packageName, row.getEntry().getChannel(), row.getEntry().getChannel(), row.getUniqueChannels(), row.getUniqueChannels(), Loading