From a30ed1e35f3db3f5f22f3f459f5c024f2e2e1f2d Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Fri, 19 Feb 2021 11:07:18 -0800 Subject: [PATCH] Add taskId to bubble xml * Save the bubble taskId to XML * Doesn't increase version # of XML, just sets the taskId as INVALID_TASK_ID if it's the old XML without taskId Test: atest BubbleXmlHelperTest Bug: 179676966 Change-Id: Ied04458fb4715a3de32784378568495128b54163 --- .../com/android/wm/shell/bubbles/Bubble.java | 7 ++- .../wm/shell/bubbles/BubbleDataRepository.kt | 12 +++-- .../wm/shell/bubbles/storage/BubbleEntity.kt | 3 +- .../shell/bubbles/storage/BubbleXmlHelper.kt | 6 ++- .../storage/BubblePersistentRepositoryTest.kt | 8 ++-- .../storage/BubbleVolatileRepositoryTest.kt | 13 +++-- .../bubbles/storage/BubbleXmlHelperTest.kt | 48 +++++++++++++++---- 7 files changed, 72 insertions(+), 25 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 0ee1f06423520..8697be9db3fd1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -124,6 +124,7 @@ public class Bubble implements BubbleViewProvider { private int mDesiredHeight; @DimenRes private int mDesiredHeightResId; + private int mTaskId; /** for logging **/ @Nullable @@ -162,7 +163,7 @@ public class Bubble implements BubbleViewProvider { */ Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo, final int desiredHeight, final int desiredHeightResId, @Nullable final String title, - Executor mainExecutor) { + int taskId, Executor mainExecutor) { Objects.requireNonNull(key); Objects.requireNonNull(shortcutInfo); mMetadataShortcutId = shortcutInfo.getId(); @@ -178,6 +179,7 @@ public class Bubble implements BubbleViewProvider { mTitle = title; mShowBubbleUpdateDot = false; mMainExecutor = mainExecutor; + mTaskId = taskId; } @VisibleForTesting(visibility = PRIVATE) @@ -197,6 +199,7 @@ public class Bubble implements BubbleViewProvider { }); }; mMainExecutor = mainExecutor; + mTaskId = INVALID_TASK_ID; setEntry(entry); } @@ -520,7 +523,7 @@ public class Bubble implements BubbleViewProvider { */ @Override public int getTaskId() { - return mExpandedView != null ? mExpandedView.getTaskId() : INVALID_TASK_ID; + return mExpandedView != null ? mExpandedView.getTaskId() : mTaskId; } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt index 3108b02cc0102..241755227af02 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt @@ -28,7 +28,6 @@ import com.android.wm.shell.bubbles.storage.BubbleEntity import com.android.wm.shell.bubbles.storage.BubblePersistentRepository import com.android.wm.shell.bubbles.storage.BubbleVolatileRepository import com.android.wm.shell.common.ShellExecutor -import com.android.wm.shell.common.annotations.ExternalThread import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -36,8 +35,11 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch import kotlinx.coroutines.yield -internal class BubbleDataRepository(context: Context, private val launcherApps: LauncherApps, - private val mainExecutor : ShellExecutor) { +internal class BubbleDataRepository( + context: Context, + private val launcherApps: LauncherApps, + private val mainExecutor: ShellExecutor +) { private val volatileRepository = BubbleVolatileRepository(launcherApps) private val persistentRepository = BubblePersistentRepository(context) @@ -78,7 +80,8 @@ internal class BubbleDataRepository(context: Context, private val launcherApps: b.key, b.rawDesiredHeight, b.rawDesiredHeightResId, - b.title + b.title, + b.taskId ) } } @@ -168,6 +171,7 @@ internal class BubbleDataRepository(context: Context, private val launcherApps: entity.desiredHeight, entity.desiredHeightResId, entity.title, + entity.taskId, mainExecutor ) } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt index aeba302bf4876..d5cab5af42e4b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt @@ -25,5 +25,6 @@ data class BubbleEntity( val key: String, val desiredHeight: Int, @DimenRes val desiredHeightResId: Int, - val title: String? = null + val title: String? = null, + val taskId: Int ) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt index fe72bd301e04d..470011b136fed 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt @@ -15,6 +15,7 @@ */ package com.android.wm.shell.bubbles.storage +import android.app.ActivityTaskManager.INVALID_TASK_ID import android.util.Xml import com.android.internal.util.FastXmlSerializer import com.android.internal.util.XmlUtils @@ -38,6 +39,7 @@ private const val ATTR_KEY = "key" private const val ATTR_DESIRED_HEIGHT = "h" private const val ATTR_DESIRED_HEIGHT_RES_ID = "hid" private const val ATTR_TITLE = "t" +private const val ATTR_TASK_ID = "tid" /** * Writes the bubbles in xml format into given output stream. @@ -70,6 +72,7 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) { serializer.attribute(null, ATTR_DESIRED_HEIGHT, bubble.desiredHeight.toString()) serializer.attribute(null, ATTR_DESIRED_HEIGHT_RES_ID, bubble.desiredHeightResId.toString()) bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) } + serializer.attribute(null, ATTR_TASK_ID, bubble.taskId.toString()) serializer.endTag(null, TAG_BUBBLE) } catch (e: IOException) { throw RuntimeException(e) @@ -103,7 +106,8 @@ private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? { parser.getAttributeWithName(ATTR_KEY) ?: return null, parser.getAttributeWithName(ATTR_DESIRED_HEIGHT)?.toInt() ?: return null, parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null, - parser.getAttributeWithName(ATTR_TITLE) + parser.getAttributeWithName(ATTR_TITLE), + parser.getAttributeWithName(ATTR_TASK_ID)?.toInt() ?: INVALID_TASK_ID ) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt index 416028088294f..bdf75fcd8816f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles.storage +import android.app.ActivityTaskManager.INVALID_TASK_ID import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase @@ -31,9 +32,10 @@ import org.junit.runner.RunWith class BubblePersistentRepositoryTest : ShellTestCase() { private val bubbles = listOf( - BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0), - BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title"), - BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0) + BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0, null, 1), + BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title", 2), + BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0, null, + INVALID_TASK_ID) ) private lateinit var repository: BubblePersistentRepository diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt index dd1a6a5a281eb..05795fde7d6c8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles.storage +import android.app.ActivityTaskManager.INVALID_TASK_ID import android.content.pm.LauncherApps import android.os.UserHandle import android.testing.AndroidTestingRunner @@ -37,10 +38,12 @@ class BubbleVolatileRepositoryTest : ShellTestCase() { private val user0 = UserHandle.of(0) private val user10 = UserHandle.of(10) - private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0) + private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0, + null, 1) private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob", - "key-2", 0, 16537428, "title") - private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0) + "key-2", 0, 16537428, "title", 2) + private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0, + null, INVALID_TASK_ID) private val bubbles = listOf(bubble1, bubble2, bubble3) @@ -105,13 +108,13 @@ class BubbleVolatileRepositoryTest : ShellTestCase() { @Test fun testAddBubbleMatchesByKey() { - val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title") + val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title", 1) repository.addBubbles(listOf(bubble)) assertEquals(bubble, repository.bubbles.get(0)) // Same key as first bubble but different entry val bubbleModified = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, - "different title") + "different title", 2) repository.addBubbles(listOf(bubbleModified)) assertEquals(bubbleModified, repository.bubbles.get(0)) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt index e0891a95c6a6f..839b873d0c238 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles.storage +import android.app.ActivityTaskManager.INVALID_TASK_ID import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase @@ -31,17 +32,18 @@ import java.io.ByteArrayOutputStream class BubbleXmlHelperTest : ShellTestCase() { private val bubbles = listOf( - BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0), - BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title"), - BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0) + BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0, null, 1), + BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title", 2), + BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null, + INVALID_TASK_ID) ) @Test fun testWriteXml() { val expectedEntries = """ - - - + + + """.trimIndent() ByteArrayOutputStream().use { writeXml(it, bubbles) @@ -56,9 +58,9 @@ class BubbleXmlHelperTest : ShellTestCase() { val src = """ - - - + + + """.trimIndent() val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8))) @@ -79,4 +81,32 @@ class BubbleXmlHelperTest : ShellTestCase() { val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8))) assertEquals("failed parsing bubbles from xml\n$src", emptyList(), actual) } + + /** + * In S we changed the XML to include a taskId, version didn't increase because we can set a + * reasonable default for taskId (INVALID_TASK_ID) if it wasn't in the XML previously, this + * tests that that works. + */ + @Test + fun testReadXMLWithoutTaskId() { + val expectedBubbles = listOf( + BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0, null, + INVALID_TASK_ID), + BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title", + INVALID_TASK_ID), + BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null, + INVALID_TASK_ID) + ) + + val src = """ + + + + + + + """.trimIndent() + val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8))) + assertEquals("failed parsing bubbles from xml\n$src", expectedBubbles, actual) + } } \ No newline at end of file