summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt (renamed from packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt12
6 files changed, 83 insertions, 23 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 0dbee663c1c9..f1b401e77fbc 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -102,6 +102,13 @@ class Bubble implements BubbleViewProvider {
return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
}
+ // TODO: Decouple Bubble from NotificationEntry and transform ShortcutInfo into Bubble
+ Bubble(ShortcutInfo shortcutInfo) {
+ mShortcutInfo = shortcutInfo;
+ mKey = shortcutInfo.getId();
+ mGroupId = shortcutInfo.getId();
+ }
+
/** Used in tests when no UI is required. */
@VisibleForTesting(visibility = PRIVATE)
Bubble(NotificationEntry e,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
index b9825e1d21e5..ba93f4125ea5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
@@ -15,24 +15,32 @@
*/
package com.android.systemui.bubbles
+import android.annotation.SuppressLint
import android.annotation.UserIdInt
+import android.content.pm.LauncherApps
+import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC
+import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER
+import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED
+import android.os.UserHandle
import android.util.Log
+import com.android.systemui.bubbles.storage.BubbleEntity
import com.android.systemui.bubbles.storage.BubblePersistentRepository
import com.android.systemui.bubbles.storage.BubbleVolatileRepository
-import com.android.systemui.bubbles.storage.BubbleXmlEntity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.launch
import kotlinx.coroutines.yield
+
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
internal class BubbleDataRepository @Inject constructor(
private val volatileRepository: BubbleVolatileRepository,
- private val persistentRepository: BubblePersistentRepository
+ private val persistentRepository: BubblePersistentRepository,
+ private val launcherApps: LauncherApps
) {
private val ioScope = CoroutineScope(Dispatchers.IO)
@@ -64,10 +72,10 @@ internal class BubbleDataRepository @Inject constructor(
if (entities.isNotEmpty()) persistToDisk()
}
- private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleXmlEntity> {
+ private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
return bubbles.mapNotNull { b ->
val shortcutId = b.shortcutInfo?.id ?: return@mapNotNull null
- BubbleXmlEntity(userId, b.packageName, shortcutId)
+ BubbleEntity(userId, b.packageName, shortcutId)
}
}
@@ -100,15 +108,60 @@ internal class BubbleDataRepository @Inject constructor(
/**
* Load bubbles from disk.
*/
+ // TODO: call this method from BubbleController and update UI
+ @SuppressLint("WrongConstant")
fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch {
- val bubbleXmlEntities = persistentRepository.readFromDisk()
- volatileRepository.addBubbles(bubbleXmlEntities)
- uiScope.launch {
- // TODO: transform bubbleXmlEntities into bubbles
- // cb(bubbles)
- }
+ /**
+ * Load BubbleEntity from disk.
+ * e.g.
+ * [
+ * BubbleEntity(0, "com.example.messenger", "id-2"),
+ * BubbleEntity(10, "com.example.chat", "my-id1")
+ * BubbleEntity(0, "com.example.messenger", "id-1")
+ * ]
+ */
+ val entities = persistentRepository.readFromDisk()
+ volatileRepository.addBubbles(entities)
+ /**
+ * Extract userId/packageName from these entities.
+ * e.g.
+ * [
+ * ShortcutKey(0, "com.example.messenger"), ShortcutKey(0, "com.example.chat")
+ * ]
+ */
+ val shortcutKeys = entities.map { ShortcutKey(it.userId, it.packageName) }.toSet()
+ /**
+ * Retrieve shortcuts with given userId/packageName combination, then construct a mapping
+ * between BubbleEntity and ShortcutInfo.
+ * e.g.
+ * {
+ * BubbleEntity(0, "com.example.messenger", "id-0") ->
+ * ShortcutInfo(userId=0, pkg="com.example.messenger", id="id-0"),
+ * BubbleEntity(0, "com.example.messenger", "id-2") ->
+ * ShortcutInfo(userId=0, pkg="com.example.messenger", id="id-2"),
+ * BubbleEntity(10, "com.example.chat", "id-1") ->
+ * ShortcutInfo(userId=10, pkg="com.example.chat", id="id-1"),
+ * BubbleEntity(10, "com.example.chat", "id-3") ->
+ * ShortcutInfo(userId=10, pkg="com.example.chat", id="id-3")
+ * }
+ */
+ val shortcutMap = shortcutKeys.flatMap { key ->
+ launcherApps.getShortcuts(
+ LauncherApps.ShortcutQuery()
+ .setPackage(key.pkg)
+ .setQueryFlags(SHORTCUT_QUERY_FLAG), UserHandle.of(key.userId))
+ ?.map { BubbleEntity(key.userId, key.pkg, it.id) to it } ?: emptyList()
+ }.toMap()
+ // For each entity loaded from xml, find the corresponding ShortcutInfo then convert them
+ // into Bubble.
+ val bubbles = entities.mapNotNull { entity -> shortcutMap[entity]?.let { Bubble(it) } }
+ uiScope.launch { cb(bubbles) }
}
+
+ private data class ShortcutKey(val userId: Int, val pkg: String)
}
private const val TAG = "BubbleDataRepository"
private const val DEBUG = false
+private const val SHORTCUT_QUERY_FLAG =
+ FLAG_MATCH_DYNAMIC or FLAG_MATCH_PINNED_BY_ANY_LAUNCHER or FLAG_MATCH_CACHED \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
index d0f76077cd51..4690a8e14072 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
@@ -17,7 +17,7 @@ package com.android.systemui.bubbles.storage
import android.annotation.UserIdInt
-data class BubbleXmlEntity(
+data class BubbleEntity(
@UserIdInt val userId: Int,
val packageName: String,
val shortcutId: String
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
index 149e2c4c4022..7c3271e4b76c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
@@ -32,7 +32,7 @@ class BubblePersistentRepository @Inject constructor(
private val bubbleFile: AtomicFile = AtomicFile(File(context.filesDir,
"overflow_bubbles.xml"), "overflow-bubbles")
- fun persistsToDisk(bubbles: List<BubbleXmlEntity>): Boolean {
+ fun persistsToDisk(bubbles: List<BubbleEntity>): Boolean {
if (DEBUG) Log.d(TAG, "persisting ${bubbles.size} bubbles")
synchronized(bubbleFile) {
val stream: FileOutputStream = try { bubbleFile.startWrite() } catch (e: IOException) {
@@ -52,7 +52,7 @@ class BubblePersistentRepository @Inject constructor(
return false
}
- fun readFromDisk(): List<BubbleXmlEntity> {
+ fun readFromDisk(): List<BubbleEntity> {
synchronized(bubbleFile) {
try { return bubbleFile.openRead().use(::readXml) } catch (e: Throwable) {
Log.e(TAG, "Failed to open bubble file", e)
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
index e1f675b83583..d1eee2f69b63 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
@@ -29,12 +29,12 @@ class BubbleVolatileRepository @Inject constructor() {
/**
* An ordered set of bubbles based on their natural ordering.
*/
- private val entities = mutableSetOf<BubbleXmlEntity>()
+ private val entities = mutableSetOf<BubbleEntity>()
/**
* Returns a snapshot of all the bubbles.
*/
- val bubbles: List<BubbleXmlEntity>
+ val bubbles: List<BubbleEntity>
@Synchronized
get() = entities.toList()
@@ -43,7 +43,7 @@ class BubbleVolatileRepository @Inject constructor() {
* it will be moved to the last.
*/
@Synchronized
- fun addBubbles(bubbles: List<BubbleXmlEntity>) {
+ fun addBubbles(bubbles: List<BubbleEntity>) {
if (bubbles.isEmpty()) return
bubbles.forEach { entities.remove(it) }
if (entities.size + bubbles.size >= CAPACITY) {
@@ -53,7 +53,7 @@ class BubbleVolatileRepository @Inject constructor() {
}
@Synchronized
- fun removeBubbles(bubbles: List<BubbleXmlEntity>) {
+ fun removeBubbles(bubbles: List<BubbleEntity>) {
bubbles.forEach { entities.remove(it) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
index 1e91653c6db7..821b64ce5e6e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
@@ -35,7 +35,7 @@ private const val ATTR_SHORTCUT_ID = "sid"
* Writes the bubbles in xml format into given output stream.
*/
@Throws(IOException::class)
-fun writeXml(stream: OutputStream, bubbles: List<BubbleXmlEntity>) {
+fun writeXml(stream: OutputStream, bubbles: List<BubbleEntity>) {
val serializer: XmlSerializer = FastXmlSerializer()
serializer.setOutput(stream, StandardCharsets.UTF_8.name())
serializer.startDocument(null, true)
@@ -51,7 +51,7 @@ fun writeXml(stream: OutputStream, bubbles: List<BubbleXmlEntity>) {
* <bb uid="0" pkg="com.example.messenger" sid="my-shortcut" />
* ```
*/
-private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleXmlEntity) {
+private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) {
try {
serializer.startTag(null, TAG_BUBBLE)
serializer.attribute(null, ATTR_USER_ID, bubble.userId.toString())
@@ -66,8 +66,8 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleXmlEntity) {
/**
* Reads the bubbles from xml file.
*/
-fun readXml(stream: InputStream): List<BubbleXmlEntity> {
- val bubbles = mutableListOf<BubbleXmlEntity>()
+fun readXml(stream: InputStream): List<BubbleEntity> {
+ val bubbles = mutableListOf<BubbleEntity>()
val parser: XmlPullParser = Xml.newPullParser()
parser.setInput(stream, StandardCharsets.UTF_8.name())
XmlUtils.beginDocument(parser, TAG_BUBBLES)
@@ -78,9 +78,9 @@ fun readXml(stream: InputStream): List<BubbleXmlEntity> {
return bubbles
}
-private fun readXmlEntry(parser: XmlPullParser): BubbleXmlEntity? {
+private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? {
while (parser.eventType != XmlPullParser.START_TAG) { parser.next() }
- return BubbleXmlEntity(
+ return BubbleEntity(
parser.getAttributeWithName(ATTR_USER_ID)?.toInt() ?: return null,
parser.getAttributeWithName(ATTR_PACKAGE) ?: return null,
parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null