diff options
| author | 2020-05-06 16:51:36 +0000 | |
|---|---|---|
| committer | 2020-05-06 16:51:36 +0000 | |
| commit | d0166e437e58321f5d0a426247ee24c2b38af9eb (patch) | |
| tree | 9294c740082a64be268def8d66b5725522938398 | |
| parent | 1876a7971775cd28b0dcf8e438d34af435008476 (diff) | |
| parent | 76ed7ba8cf3bd88cb0e2efa85d4d34e3ac0314f4 (diff) | |
Merge "Persists bubbles to disk (part 2)" into rvc-dev
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 |