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

Commit 9cb34c46 authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Reinflate active notifications when SHOW_NOTIFICATION_SNOOZE setting changes.

Test: atest PreparationCoordinatorTest NotifUiAdjustmentProviderTest
Fixes: 185399616
Merged-In: I2cc194ad604953933fb14c52cecb6151a7deee11
Change-Id: I2cc194ad604953933fb14c52cecb6151a7deee11
parent 1c7adc90
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ class NotifUiAdjustment internal constructor(
    val smartActions: List<Notification.Action>,
    val smartReplies: List<CharSequence>,
    val isConversation: Boolean,
    val isSnoozeEnabled: Boolean,
    val isMinimized: Boolean,
    val needsRedaction: Boolean,
) {
@@ -42,6 +43,7 @@ class NotifUiAdjustment internal constructor(
        ): Boolean = when {
            oldAdjustment === newAdjustment -> false
            oldAdjustment.isConversation != newAdjustment.isConversation -> true
            oldAdjustment.isSnoozeEnabled != newAdjustment.isSnoozeEnabled -> true
            oldAdjustment.isMinimized != newAdjustment.isMinimized -> true
            oldAdjustment.needsRedaction != newAdjustment.needsRedaction -> true
            areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions) -> true
+29 −1
Original line number Diff line number Diff line
@@ -16,12 +16,18 @@

package com.android.systemui.statusbar.notification.collection.inflation

import android.database.ContentObserver
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.util.ListenerSet
import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject

/**
@@ -30,14 +36,23 @@ import javax.inject.Inject
 */
@SysUISingleton
class NotifUiAdjustmentProvider @Inject constructor(
    @Main private val handler: Handler,
    private val secureSettings: SecureSettings,
    private val lockscreenUserManager: NotificationLockscreenUserManager,
    private val sectionStyleProvider: SectionStyleProvider
) {
    private val dirtyListeners = ListenerSet<Runnable>()
    private var isSnoozeEnabled = false

    fun addDirtyListener(listener: Runnable) {
        if (dirtyListeners.isEmpty()) {
            lockscreenUserManager.addNotificationStateChangedListener(notifStateChangedListener)
            updateSnoozeEnabled()
            secureSettings.registerContentObserverForUser(
                SHOW_NOTIFICATION_SNOOZE,
                settingsObserver,
                UserHandle.USER_ALL
            )
        }
        dirtyListeners.addIfAbsent(listener)
    }
@@ -46,6 +61,7 @@ class NotifUiAdjustmentProvider @Inject constructor(
        dirtyListeners.remove(listener)
        if (dirtyListeners.isEmpty()) {
            lockscreenUserManager.removeNotificationStateChangedListener(notifStateChangedListener)
            secureSettings.unregisterContentObserver(settingsObserver)
        }
    }

@@ -54,6 +70,17 @@ class NotifUiAdjustmentProvider @Inject constructor(
            dirtyListeners.forEach(Runnable::run)
        }

    private val settingsObserver = object : ContentObserver(handler) {
        override fun onChange(selfChange: Boolean) {
            updateSnoozeEnabled()
            dirtyListeners.forEach(Runnable::run)
        }
    }

    private fun updateSnoozeEnabled() {
        isSnoozeEnabled = secureSettings.getInt(SHOW_NOTIFICATION_SNOOZE, 0) == 1
    }

    private fun isEntryMinimized(entry: NotificationEntry): Boolean {
        val section = entry.section ?: error("Entry must have a section to determine if minimized")
        val parent = entry.parent ?: error("Entry must have a parent to determine if minimized")
@@ -73,6 +100,7 @@ class NotifUiAdjustmentProvider @Inject constructor(
        smartActions = entry.ranking.smartActions,
        smartReplies = entry.ranking.smartReplies,
        isConversation = entry.ranking.isConversation,
        isSnoozeEnabled = isSnoozeEnabled,
        isMinimized = isEntryMinimized(entry),
        needsRedaction = lockscreenUserManager.needsRedaction(entry),
    )
+9 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;

import static java.util.Objects.requireNonNull;

import android.os.Handler;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -59,6 +60,7 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider;
import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import com.android.systemui.util.settings.SecureSettings;

import org.junit.Before;
import org.junit.Test;
@@ -97,6 +99,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
    @Mock private IStatusBarService mService;
    @Mock private BindEventManagerImpl mBindEventManagerImpl;
    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
    @Mock private Handler mHandler;
    @Mock private SecureSettings mSecureSettings;
    @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
    private final SectionStyleProvider mSectionStyleProvider = new SectionStyleProvider();

@@ -110,8 +114,11 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mAdjustmentProvider =
            new NotifUiAdjustmentProvider(mLockscreenUserManager, mSectionStyleProvider);
        mAdjustmentProvider = new NotifUiAdjustmentProvider(
                mHandler,
                mSecureSettings,
                mLockscreenUserManager,
                mSectionStyleProvider);
        mEntry = getNotificationEntryBuilder().setParent(ROOT_ENTRY).build();
        mInflationError = new Exception(TEST_MESSAGE);
        mErrorManager = new NotifInflationErrorManager();
+88 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.collection.inflation

import android.database.ContentObserver
import android.os.Handler
import android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever

@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -18,12 +49,39 @@ import org.mockito.Mockito.verify
class NotifUiAdjustmentProviderTest : SysuiTestCase() {
    private val lockscreenUserManager: NotificationLockscreenUserManager = mock()
    private val sectionStyleProvider: SectionStyleProvider = mock()
    private val handler: Handler = mock()
    private val secureSettings: SecureSettings = mock()
    private val uri = FakeSettings().getUriFor(SHOW_NOTIFICATION_SNOOZE)
    private val dirtyListener: Runnable = mock()

    private val section = NotifSection(mock(), 0)
    private val entry = NotificationEntryBuilder()
        .setSection(section)
        .setParent(GroupEntry.ROOT_ENTRY)
        .build()

    private lateinit var contentObserver: ContentObserver

    private val adjustmentProvider = NotifUiAdjustmentProvider(
        handler,
        secureSettings,
        lockscreenUserManager,
        sectionStyleProvider,
    )

    @Before
    fun setup() {
        verifyNoMoreInteractions(secureSettings)
        adjustmentProvider.addDirtyListener(dirtyListener)
        verify(secureSettings).getInt(eq(SHOW_NOTIFICATION_SNOOZE), any())
        contentObserver = withArgCaptor {
            verify(secureSettings).registerContentObserverForUser(
                eq(SHOW_NOTIFICATION_SNOOZE), capture(), any()
            )
        }
        verifyNoMoreInteractions(secureSettings, dirtyListener)
    }

    @Test
    fun notifLockscreenStateChangeWillNotifDirty() {
        val dirtyListener = mock<Runnable>()
@@ -33,6 +91,35 @@ class NotifUiAdjustmentProviderTest : SysuiTestCase() {
                verify(lockscreenUserManager).addNotificationStateChangedListener(capture())
            }
        notifLocksreenStateChangeListener.onNotificationStateChanged()
        verify(dirtyListener).run();
        verify(dirtyListener).run()
    }

    @Test
    fun additionalAddDoesNotRegisterAgain() {
        clearInvocations(secureSettings)
        adjustmentProvider.addDirtyListener(mock())
        verifyNoMoreInteractions(secureSettings)
    }

    @Test
    fun onChangeWillQueryThenNotifyDirty() {
        contentObserver.onChange(false, listOf(uri), 0, 0)
        with(inOrder(secureSettings, dirtyListener)) {
            verify(secureSettings).getInt(eq(SHOW_NOTIFICATION_SNOOZE), any())
            verify(dirtyListener).run()
        }
    }

    @Test
    fun changingSnoozeChangesProvidedAdjustment() {
        whenever(secureSettings.getInt(eq(SHOW_NOTIFICATION_SNOOZE), any())).thenReturn(0)
        val original = adjustmentProvider.calculateAdjustment(entry)
        assertThat(original.isSnoozeEnabled).isFalse()

        whenever(secureSettings.getInt(eq(SHOW_NOTIFICATION_SNOOZE), any())).thenReturn(1)
        contentObserver.onChange(false, listOf(uri), 0, 0)
        val withSnoozing = adjustmentProvider.calculateAdjustment(entry)
        assertThat(withSnoozing.isSnoozeEnabled).isTrue()
        assertThat(withSnoozing).isNotEqualTo(original)
    }
}