blob: 1e91653c6db79807312c499d348a59631f7fffb3 [file] [log] [blame]
Pinyao Tingee191b12020-04-29 18:35:39 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.systemui.bubbles.storage
17
18import com.android.internal.util.FastXmlSerializer
19import org.xmlpull.v1.XmlSerializer
20import java.io.IOException
Pinyao Ting76ed7ba2020-04-29 18:35:39 -070021import android.util.Xml
22import com.android.internal.util.XmlUtils
23import org.xmlpull.v1.XmlPullParser
24import java.io.InputStream
Pinyao Tingee191b12020-04-29 18:35:39 -070025import java.io.OutputStream
26import java.nio.charset.StandardCharsets
27
28private const val TAG_BUBBLES = "bs"
29private const val TAG_BUBBLE = "bb"
30private const val ATTR_USER_ID = "uid"
31private const val ATTR_PACKAGE = "pkg"
32private const val ATTR_SHORTCUT_ID = "sid"
33
34/**
35 * Writes the bubbles in xml format into given output stream.
36 */
37@Throws(IOException::class)
38fun writeXml(stream: OutputStream, bubbles: List<BubbleXmlEntity>) {
39 val serializer: XmlSerializer = FastXmlSerializer()
40 serializer.setOutput(stream, StandardCharsets.UTF_8.name())
41 serializer.startDocument(null, true)
42 serializer.startTag(null, TAG_BUBBLES)
43 bubbles.forEach { b -> writeXmlEntry(serializer, b) }
44 serializer.endTag(null, TAG_BUBBLES)
45 serializer.endDocument()
46}
47
48/**
49 * Creates a xml entry for given bubble in following format:
50 * ```
51 * <bb uid="0" pkg="com.example.messenger" sid="my-shortcut" />
52 * ```
53 */
54private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleXmlEntity) {
55 try {
56 serializer.startTag(null, TAG_BUBBLE)
57 serializer.attribute(null, ATTR_USER_ID, bubble.userId.toString())
58 serializer.attribute(null, ATTR_PACKAGE, bubble.packageName)
59 serializer.attribute(null, ATTR_SHORTCUT_ID, bubble.shortcutId)
60 serializer.endTag(null, TAG_BUBBLE)
61 } catch (e: IOException) {
62 throw RuntimeException(e)
63 }
Pinyao Ting76ed7ba2020-04-29 18:35:39 -070064}
65
66/**
67 * Reads the bubbles from xml file.
68 */
69fun readXml(stream: InputStream): List<BubbleXmlEntity> {
70 val bubbles = mutableListOf<BubbleXmlEntity>()
71 val parser: XmlPullParser = Xml.newPullParser()
72 parser.setInput(stream, StandardCharsets.UTF_8.name())
73 XmlUtils.beginDocument(parser, TAG_BUBBLES)
74 val outerDepth = parser.depth
75 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
76 bubbles.add(readXmlEntry(parser) ?: continue)
77 }
78 return bubbles
79}
80
81private fun readXmlEntry(parser: XmlPullParser): BubbleXmlEntity? {
82 while (parser.eventType != XmlPullParser.START_TAG) { parser.next() }
83 return BubbleXmlEntity(
84 parser.getAttributeWithName(ATTR_USER_ID)?.toInt() ?: return null,
85 parser.getAttributeWithName(ATTR_PACKAGE) ?: return null,
86 parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null
87 )
88}
89
90private fun XmlPullParser.getAttributeWithName(name: String): String? {
91 for (i in 0 until attributeCount) {
92 if (getAttributeName(i) == name) return getAttributeValue(i)
93 }
94 return null
Pinyao Tingee191b12020-04-29 18:35:39 -070095}