1 /*
<lambda>null2  * Copyright (C) 2022 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  */
16 
17 package com.android.server.permission.access.appop
18 
19 import android.util.Slog
20 import com.android.modules.utils.BinaryXmlPullParser
21 import com.android.modules.utils.BinaryXmlSerializer
22 import com.android.server.permission.access.AccessState
23 import com.android.server.permission.access.MutableAccessState
24 import com.android.server.permission.access.MutablePackageAppOpModes
25 import com.android.server.permission.access.PackageAppOpModes
26 import com.android.server.permission.access.WriteMode
27 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
28 import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
29 import com.android.server.permission.access.util.attributeInterned
30 import com.android.server.permission.access.util.forEachTag
31 import com.android.server.permission.access.util.getAttributeValueOrThrow
32 import com.android.server.permission.access.util.tag
33 import com.android.server.permission.access.util.tagName
34 
35 class PackageAppOpPersistence : BaseAppOpPersistence() {
36     override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
37         when (tagName) {
38             TAG_PACKAGE_APP_OPS -> parsePackageAppOps(state, userId)
39             else -> {}
40         }
41     }
42 
43     private fun BinaryXmlPullParser.parsePackageAppOps(state: MutableAccessState, userId: Int) {
44         val userState = state.mutateUserState(userId, WriteMode.NONE)!!
45         val packageAppOpModes = userState.mutatePackageAppOpModes()
46         forEachTag {
47             when (tagName) {
48                 TAG_PACKAGE -> parsePackage(packageAppOpModes)
49                 else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
50             }
51         }
52         packageAppOpModes.forEachReversedIndexed { packageNameIndex, packageName, _ ->
53             if (packageName !in state.externalState.packageStates) {
54                 Slog.w(LOG_TAG, "Dropping unknown package $packageName when parsing app-op state")
55                 packageAppOpModes.removeAt(packageNameIndex)
56                 userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
57             }
58         }
59     }
60 
61     private fun BinaryXmlPullParser.parsePackage(packageAppOpModes: MutablePackageAppOpModes) {
62         val packageName = getAttributeValueOrThrow(ATTR_NAME).intern()
63         val appOpModes = MutableIndexedMap<String, Int>()
64         packageAppOpModes[packageName] = appOpModes
65         parseAppOps(appOpModes)
66     }
67 
68     override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
69         serializePackageAppOps(state.userStates[userId]!!.packageAppOpModes)
70     }
71 
72     private fun BinaryXmlSerializer.serializePackageAppOps(packageAppOpModes: PackageAppOpModes) {
73         tag(TAG_PACKAGE_APP_OPS) {
74             packageAppOpModes.forEachIndexed { _, packageName, appOpModes ->
75                 serializePackage(packageName, appOpModes)
76             }
77         }
78     }
79 
80     private fun BinaryXmlSerializer.serializePackage(
81         packageName: String,
82         appOpModes: IndexedMap<String, Int>
83     ) {
84         tag(TAG_PACKAGE) {
85             attributeInterned(ATTR_NAME, packageName)
86             serializeAppOps(appOpModes)
87         }
88     }
89 
90     companion object {
91         private val LOG_TAG = PackageAppOpPersistence::class.java.simpleName
92 
93         private const val TAG_PACKAGE = "package"
94         private const val TAG_PACKAGE_APP_OPS = "package-app-ops"
95 
96         private const val ATTR_NAME = "name"
97     }
98 }
99