summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pinyao Ting <pinyaoting@google.com> 2020-05-06 16:51:36 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-05-06 16:51:36 +0000
commitd0166e437e58321f5d0a426247ee24c2b38af9eb (patch)
tree9294c740082a64be268def8d66b5725522938398
parent1876a7971775cd28b0dcf8e438d34af435008476 (diff)
parent76ed7ba8cf3bd88cb0e2efa85d4d34e3ac0314f4 (diff)
Merge "Persists bubbles to disk (part 2)" into rvc-dev
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt12
-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.kt35
4 files changed, 82 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
index 63dd801be7ca..b9825e1d21e5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bubbles
import android.annotation.UserIdInt
+import android.util.Log
import com.android.systemui.bubbles.storage.BubblePersistentRepository
import com.android.systemui.bubbles.storage.BubbleVolatileRepository
import com.android.systemui.bubbles.storage.BubbleXmlEntity
@@ -35,36 +36,39 @@ internal class BubbleDataRepository @Inject constructor(
) {
private val ioScope = CoroutineScope(Dispatchers.IO)
+ private val uiScope = CoroutineScope(Dispatchers.Main)
private var job: Job? = null
/**
* Adds the bubble in memory, then persists the snapshot after adding the bubble to disk
* asynchronously.
*/
- fun addBubble(@UserIdInt userId: Int, bubble: Bubble) {
- volatileRepository.addBubble(
- BubbleXmlEntity(userId, bubble.packageName, bubble.shortcutInfo?.id ?: return))
- persistToDisk()
- }
+ fun addBubble(@UserIdInt userId: Int, bubble: Bubble) = addBubbles(userId, listOf(bubble))
/**
* Adds the bubble in memory, then persists the snapshot after adding the bubble to disk
* asynchronously.
*/
fun addBubbles(@UserIdInt userId: Int, bubbles: List<Bubble>) {
- volatileRepository.addBubbles(bubbles.mapNotNull {
- val shortcutId = it.shortcutInfo?.id ?: return@mapNotNull null
- BubbleXmlEntity(userId, it.packageName, shortcutId)
- })
- persistToDisk()
+ if (DEBUG) Log.d(TAG, "adding ${bubbles.size} bubbles")
+ val entities = transform(userId, bubbles).also(volatileRepository::addBubbles)
+ if (entities.isNotEmpty()) persistToDisk()
}
+ /**
+ * Removes the bubbles from memory, then persists the snapshot to disk asynchronously.
+ */
fun removeBubbles(@UserIdInt userId: Int, bubbles: List<Bubble>) {
- volatileRepository.removeBubbles(bubbles.mapNotNull {
- val shortcutId = it.shortcutInfo?.id ?: return@mapNotNull null
- BubbleXmlEntity(userId, it.packageName, shortcutId)
- })
- persistToDisk()
+ if (DEBUG) Log.d(TAG, "removing ${bubbles.size} bubbles")
+ val entities = transform(userId, bubbles).also(volatileRepository::removeBubbles)
+ if (entities.isNotEmpty()) persistToDisk()
+ }
+
+ private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleXmlEntity> {
+ return bubbles.mapNotNull { b ->
+ val shortcutId = b.shortcutInfo?.id ?: return@mapNotNull null
+ BubbleXmlEntity(userId, b.packageName, shortcutId)
+ }
}
/**
@@ -92,4 +96,19 @@ internal class BubbleDataRepository @Inject constructor(
persistentRepository.persistsToDisk(volatileRepository.bubbles)
}
}
+
+ /**
+ * Load bubbles from disk.
+ */
+ fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch {
+ val bubbleXmlEntities = persistentRepository.readFromDisk()
+ volatileRepository.addBubbles(bubbleXmlEntities)
+ uiScope.launch {
+ // TODO: transform bubbleXmlEntities into bubbles
+ // cb(bubbles)
+ }
+ }
}
+
+private const val TAG = "BubbleDataRepository"
+private const val DEBUG = false
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 b2495c658948..149e2c4c4022 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
@@ -33,6 +33,7 @@ class BubblePersistentRepository @Inject constructor(
"overflow_bubbles.xml"), "overflow-bubbles")
fun persistsToDisk(bubbles: List<BubbleXmlEntity>): Boolean {
+ if (DEBUG) Log.d(TAG, "persisting ${bubbles.size} bubbles")
synchronized(bubbleFile) {
val stream: FileOutputStream = try { bubbleFile.startWrite() } catch (e: IOException) {
Log.e(TAG, "Failed to save bubble file", e)
@@ -41,6 +42,7 @@ class BubblePersistentRepository @Inject constructor(
try {
writeXml(stream, bubbles)
bubbleFile.finishWrite(stream)
+ if (DEBUG) Log.d(TAG, "persisted ${bubbles.size} bubbles")
return true
} catch (e: Exception) {
Log.e(TAG, "Failed to save bubble file, restoring backup", e)
@@ -49,6 +51,16 @@ class BubblePersistentRepository @Inject constructor(
}
return false
}
+
+ fun readFromDisk(): List<BubbleXmlEntity> {
+ synchronized(bubbleFile) {
+ try { return bubbleFile.openRead().use(::readXml) } catch (e: Throwable) {
+ Log.e(TAG, "Failed to open bubble file", e)
+ }
+ return emptyList()
+ }
+ }
}
private const val TAG = "BubblePersistentRepository"
+private const val DEBUG = false
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 3dba26807485..e1f675b83583 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
@@ -39,12 +39,6 @@ class BubbleVolatileRepository @Inject constructor() {
get() = entities.toList()
/**
- * Add the bubble to memory and perform a de-duplication. In case the bubble already exists,
- * the bubble will be moved to the last.
- */
- fun addBubble(bubble: BubbleXmlEntity) = addBubbles(listOf(bubble))
-
- /**
* Add the bubbles to memory and perform a de-duplication. In case a bubble already exists,
* it will be moved to the last.
*/
@@ -55,7 +49,7 @@ class BubbleVolatileRepository @Inject constructor() {
if (entities.size + bubbles.size >= CAPACITY) {
entities.drop(entities.size + bubbles.size - CAPACITY)
}
- entities.addAll(bubbles.reversed())
+ entities.addAll(bubbles)
}
@Synchronized
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 3192f34b69fd..1e91653c6db7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
@@ -18,6 +18,10 @@ package com.android.systemui.bubbles.storage
import com.android.internal.util.FastXmlSerializer
import org.xmlpull.v1.XmlSerializer
import java.io.IOException
+import android.util.Xml
+import com.android.internal.util.XmlUtils
+import org.xmlpull.v1.XmlPullParser
+import java.io.InputStream
import java.io.OutputStream
import java.nio.charset.StandardCharsets
@@ -57,4 +61,35 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleXmlEntity) {
} catch (e: IOException) {
throw RuntimeException(e)
}
+}
+
+/**
+ * Reads the bubbles from xml file.
+ */
+fun readXml(stream: InputStream): List<BubbleXmlEntity> {
+ val bubbles = mutableListOf<BubbleXmlEntity>()
+ val parser: XmlPullParser = Xml.newPullParser()
+ parser.setInput(stream, StandardCharsets.UTF_8.name())
+ XmlUtils.beginDocument(parser, TAG_BUBBLES)
+ val outerDepth = parser.depth
+ while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+ bubbles.add(readXmlEntry(parser) ?: continue)
+ }
+ return bubbles
+}
+
+private fun readXmlEntry(parser: XmlPullParser): BubbleXmlEntity? {
+ while (parser.eventType != XmlPullParser.START_TAG) { parser.next() }
+ return BubbleXmlEntity(
+ parser.getAttributeWithName(ATTR_USER_ID)?.toInt() ?: return null,
+ parser.getAttributeWithName(ATTR_PACKAGE) ?: return null,
+ parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null
+ )
+}
+
+private fun XmlPullParser.getAttributeWithName(name: String): String? {
+ for (i in 0 until attributeCount) {
+ if (getAttributeName(i) == name) return getAttributeValue(i)
+ }
+ return null
} \ No newline at end of file