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

Commit ab8c81bc authored by András Kurucz's avatar András Kurucz
Browse files

Fix missing notifs after restoring Overflow Bubbles

When you swipe away a notification in the shade and that notification has a restored Overflow Bubble, the shade does not update to fill the blank space.

How does this happen:
- ShadeListBuilder depends on BubbleCoordinator's NotifFilter to tell it which notifications to filter out
- BubbleCoordinator checks BubbleController's CachedState to see which notifications to suppress
- BubbleController's CachedState is not updated to suppress the Notification, because
- Bubble #setSuppressNotification thinks that we should still display the Notif in the shade, because
- In Bubble #showInShade always returned true, becase the #mIsClearable is set to false for all restored Overflow Bubbles

Why doesn't it happen with Bubbles in the stack:
- if a Bubble is in the Stack, we don't read its data from the Overflow Bubbles
- after a restart, Bubbles in the Stack are freshly created from restored NotificationEntries in BubblesManager#mSysuiProxy#getShouldRestoredEntries
- NotificationEntry#isDismissable is used to set BubbleEntry#isClearable here, which field is preserved

This change
- writes Bubble#mIsClearable to the bubble xml, so we won't have this problem with restoring Overflow Bubbles
- fixes SparseArray comparison in BubbleXmlHelperTest and BubblePersistentRepositoryTest as previously we were not comparing values stored with the same key

Fixes: 237897866

Test: have some Notifications which belongs to Overflow Bubbles (the max number of Bubbles is 5, if we receive more Notifs, the oldest Bubble will be pushed to the Overflow)
=> restart SystemUI with `adb shell am crash com.android.systemui`
=> swipe away shade notification for the chats
=> see that notifs below move up to fill blank space

Test: atest BubbleXmlHelperTest BubblePersistentRepositoryTest

Change-Id: I621b72a54db0034e4c66c69838bd266401c02f9b
parent 41aeadba
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.os.AsyncTask.Status.FINISHED;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;

import android.annotation.DimenRes;
import android.annotation.Hide;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
@@ -180,7 +181,7 @@ public class Bubble implements BubbleViewProvider {
    @VisibleForTesting(visibility = PRIVATE)
    public Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
            final int desiredHeight, final int desiredHeightResId, @Nullable final String title,
            int taskId, @Nullable final String locus, Executor mainExecutor,
            int taskId, @Nullable final String locus, boolean isClearable, Executor mainExecutor,
            final Bubbles.BubbleMetadataFlagListener listener) {
        Objects.requireNonNull(key);
        Objects.requireNonNull(shortcutInfo);
@@ -189,6 +190,7 @@ public class Bubble implements BubbleViewProvider {
        mKey = key;
        mGroupKey = null;
        mLocusId = locus != null ? new LocusId(locus) : null;
        mIsClearable = isClearable;
        mFlags = 0;
        mUser = shortcutInfo.getUserHandle();
        mPackageName = shortcutInfo.getPackage();
@@ -245,6 +247,11 @@ public class Bubble implements BubbleViewProvider {
        return mKey;
    }

    @Hide
    public boolean isClearable() {
        return mIsClearable;
    }

    /**
     * @see StatusBarNotification#getGroupKey()
     * @return the group key for this bubble, if one exists.
+3 −1
Original line number Diff line number Diff line
@@ -109,7 +109,8 @@ internal class BubbleDataRepository(
                    b.rawDesiredHeightResId,
                    b.title,
                    b.taskId,
                    b.locusId?.id
                    b.locusId?.id,
                    b.isClearable
            )
        }
    }
@@ -205,6 +206,7 @@ internal class BubbleDataRepository(
                                entity.title,
                                entity.taskId,
                                entity.locus,
                                entity.isClearable,
                                mainExecutor,
                                bubbleMetadataFlagListener
                        )
+2 −1
Original line number Diff line number Diff line
@@ -27,5 +27,6 @@ data class BubbleEntity(
    @DimenRes val desiredHeightResId: Int,
    val title: String? = null,
    val taskId: Int,
    val locus: String? = null
    val locus: String? = null,
    val isClearable: Boolean = false
)
+6 −1
Original line number Diff line number Diff line
@@ -44,6 +44,9 @@ private const val ATTR_TITLE = "t"
private const val ATTR_TASK_ID = "tid"
private const val ATTR_LOCUS = "l"

// TODO rename it to dismissable to follow NotificationEntry namings
private const val ATTR_CLEARABLE = "d"

/**
 * Writes the bubbles in xml format into given output stream.
 */
@@ -84,6 +87,7 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) {
        bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) }
        serializer.attribute(null, ATTR_TASK_ID, bubble.taskId.toString())
        bubble.locus?.let { serializer.attribute(null, ATTR_LOCUS, it) }
        serializer.attribute(null, ATTR_CLEARABLE, bubble.isClearable.toString())
        serializer.endTag(null, TAG_BUBBLE)
    } catch (e: IOException) {
        throw RuntimeException(e)
@@ -142,7 +146,8 @@ private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? {
            parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null,
            parser.getAttributeWithName(ATTR_TITLE),
            parser.getAttributeWithName(ATTR_TASK_ID)?.toInt() ?: INVALID_TASK_ID,
            parser.getAttributeWithName(ATTR_LOCUS)
            parser.getAttributeWithName(ATTR_LOCUS),
            parser.getAttributeWithName(ATTR_CLEARABLE)?.toBoolean() ?: false
    )
}

+5 −4
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.testing.AndroidTestingRunner
import android.util.SparseArray
import androidx.test.filters.SmallTest
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.bubbles.storage.BubbleXmlHelperTest.Companion.sparseArraysEqual
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertNotNull
import junit.framework.Assert.assertTrue
@@ -36,7 +35,8 @@ class BubblePersistentRepositoryTest : ShellTestCase() {

    // user, package, shortcut, notification key, height, res-height, title, taskId, locusId
    private val user0Bubbles = listOf(
            BubbleEntity(0, "com.example.messenger", "shortcut-1", "0k1", 120, 0, null, 1, null),
            BubbleEntity(0, "com.example.messenger", "shortcut-1", "0k1", 120, 0, null, 1, null,
                    true),
            BubbleEntity(10, "com.example.chat", "alice and bob", "0k2", 0, 16537428, "title", 2,
                    null),
            BubbleEntity(0, "com.example.messenger", "shortcut-2", "0k3", 120, 0, null,
@@ -44,7 +44,8 @@ class BubblePersistentRepositoryTest : ShellTestCase() {
    )

    private val user1Bubbles = listOf(
            BubbleEntity(1, "com.example.messenger", "shortcut-1", "1k1", 120, 0, null, 3, null),
            BubbleEntity(1, "com.example.messenger", "shortcut-1", "1k1", 120, 0, null, 3, null,
                    true),
            BubbleEntity(12, "com.example.chat", "alice and bob", "1k2", 0, 16537428, "title", 4,
                    null),
            BubbleEntity(1, "com.example.messenger", "shortcut-2", "1k3", 120, 0, null,
@@ -76,6 +77,6 @@ class BubblePersistentRepositoryTest : ShellTestCase() {
        assertEquals(actual.size(), 0)

        repository.persistsToDisk(bubbles)
        assertTrue(sparseArraysEqual(bubbles, repository.readFromDisk()))
        assertTrue(bubbles.contentEquals(repository.readFromDisk()))
    }
}
Loading