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.os.Process
20 import android.util.Slog
21 import com.android.modules.utils.BinaryXmlPullParser
22 import com.android.modules.utils.BinaryXmlSerializer
23 import com.android.server.permission.access.AccessState
24 import com.android.server.permission.access.AppIdAppOpModes
25 import com.android.server.permission.access.MutableAccessState
26 import com.android.server.permission.access.MutableAppIdAppOpModes
27 import com.android.server.permission.access.WriteMode
28 import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
29 import com.android.server.permission.access.util.attributeInt
30 import com.android.server.permission.access.util.forEachTag
31 import com.android.server.permission.access.util.getAttributeIntOrThrow
32 import com.android.server.permission.access.util.tag
33 import com.android.server.permission.access.util.tagName
34 
35 class AppIdAppOpPersistence : BaseAppOpPersistence() {
36     override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
37         when (tagName) {
38             TAG_APP_ID_APP_OPS -> parseAppIdAppOps(state, userId)
39             else -> {}
40         }
41     }
42 
43     private fun BinaryXmlPullParser.parseAppIdAppOps(state: MutableAccessState, userId: Int) {
44         val userState = state.mutateUserState(userId, WriteMode.NONE)!!
45         val appIdAppOpModes = userState.mutateAppIdAppOpModes()
46         forEachTag {
47             when (tagName) {
48                 TAG_APP_ID -> parseAppId(appIdAppOpModes)
49                 else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
50             }
51         }
52         userState.appIdAppOpModes.forEachReversedIndexed { appIdIndex, appId, _ ->
53             // Non-application UIDs may not have an Android package but may still have app op state.
54             if (
55                 appId !in state.externalState.appIdPackageNames &&
56                     appId >= Process.FIRST_APPLICATION_UID
57             ) {
58                 Slog.w(LOG_TAG, "Dropping unknown app ID $appId when parsing app-op state")
59                 appIdAppOpModes.removeAt(appIdIndex)
60                 userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
61             }
62         }
63     }
64 
65     private fun BinaryXmlPullParser.parseAppId(appIdAppOpModes: MutableAppIdAppOpModes) {
66         val appId = getAttributeIntOrThrow(ATTR_ID)
67         val appOpModes = MutableIndexedMap<String, Int>()
68         appIdAppOpModes[appId] = appOpModes
69         parseAppOps(appOpModes)
70     }
71 
72     override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
73         serializeAppIdAppOps(state.userStates[userId]!!.appIdAppOpModes)
74     }
75 
76     private fun BinaryXmlSerializer.serializeAppIdAppOps(appIdAppOpModes: AppIdAppOpModes) {
77         tag(TAG_APP_ID_APP_OPS) {
78             appIdAppOpModes.forEachIndexed { _, appId, appOpModes ->
79                 serializeAppId(appId, appOpModes)
80             }
81         }
82     }
83 
84     private fun BinaryXmlSerializer.serializeAppId(
85         appId: Int,
86         appOpModes: IndexedMap<String, Int>
87     ) {
88         tag(TAG_APP_ID) {
89             attributeInt(ATTR_ID, appId)
90             serializeAppOps(appOpModes)
91         }
92     }
93 
94     companion object {
95         private val LOG_TAG = AppIdAppOpPersistence::class.java.simpleName
96 
97         private const val TAG_APP_ID = "app-id"
98         private const val TAG_APP_ID_APP_OPS = "app-id-app-ops"
99 
100         private const val ATTR_ID = "id"
101     }
102 }
103