1 /*
2  * Copyright (C) 2021 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
18 
19 import android.content.pm.PermissionGroupInfo
20 import com.android.server.SystemConfig
21 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
22 import com.android.server.permission.access.permission.Permission
23 import com.android.server.pm.permission.PermissionAllowlist
24 import com.android.server.pm.pkg.PackageState
25 
26 class AccessState private constructor(
27     val systemState: SystemState,
28     val userStates: IntMap<UserState>
29 ) {
30     constructor() : this(
31         SystemState(),
32         IntMap()
33     )
34 
35     fun copy(): AccessState = AccessState(
36         systemState.copy(),
37         userStates.copy { it.copy() }
38     )
39 }
40 
41 class SystemState private constructor(
42     val userIds: IntSet,
43     var packageStates: Map<String, PackageState>,
44     var disabledSystemPackageStates: Map<String, PackageState>,
45     val appIds: IntMap<IndexedListSet<String>>,
46     // Mapping from KnownPackages keys to package names.
47     var knownPackages: IntMap<Array<String>>,
48     var isLeanback: Boolean,
49     var configPermissions: Map<String, SystemConfig.PermissionEntry>,
50     var privilegedPermissionAllowlistPackages: IndexedListSet<String>,
51     var permissionAllowlist: PermissionAllowlist,
52     var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
53     var isSystemReady: Boolean,
54     // TODO: Get and watch the state for deviceAndProfileOwners
55     // Mapping from user ID to package name.
56     var deviceAndProfileOwners: IntMap<String>,
57     val permissionGroups: IndexedMap<String, PermissionGroupInfo>,
58     val permissionTrees: IndexedMap<String, Permission>,
59     val permissions: IndexedMap<String, Permission>
60 ) : WritableState() {
61     constructor() : this(
62         IntSet(),
63         emptyMap(),
64         emptyMap(),
65         IntMap(),
66         IntMap(),
67         false,
68         emptyMap(),
69         IndexedListSet(),
70         PermissionAllowlist(),
71         IndexedMap(),
72         false,
73         IntMap(),
74         IndexedMap(),
75         IndexedMap(),
76         IndexedMap()
77     )
78 
79     fun copy(): SystemState =
80         SystemState(
81             userIds.copy(),
82             packageStates,
83             disabledSystemPackageStates,
84             appIds.copy { it.copy() },
85             knownPackages,
86             isLeanback,
87             configPermissions,
88             privilegedPermissionAllowlistPackages,
89             permissionAllowlist,
90             implicitToSourcePermissions,
91             isSystemReady,
92             deviceAndProfileOwners,
93             permissionGroups.copy { it },
94             permissionTrees.copy { it },
95             permissions.copy { it }
96         )
97 }
98 
99 class UserState private constructor(
100     // A map of (appId to a map of (permissionName to permissionFlags))
101     val uidPermissionFlags: IntMap<IndexedMap<String, Int>>,
102     // appId -> opName -> opCode
103     val uidAppOpModes: IntMap<IndexedMap<String, Int>>,
104     // packageName -> opName -> opCode
105     val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>>
106 ) : WritableState() {
107     constructor() : this(
108         IntMap(),
109         IntMap(),
110         IndexedMap()
111     )
112 
113     fun copy(): UserState = UserState(
114         uidPermissionFlags.copy { it.copy { it } },
115         uidAppOpModes.copy { it.copy { it } },
116         packageAppOpModes.copy { it.copy { it } }
117     )
118 }
119 
120 object WriteMode {
121     const val NONE = 0
122     const val SYNC = 1
123     const val ASYNC = 2
124 }
125 
126 abstract class WritableState {
127     var writeMode: Int = WriteMode.NONE
128         private set
129 
130     fun requestWrite(sync: Boolean = false) {
131         if (sync) {
132             writeMode = WriteMode.SYNC
133         } else {
134             if (writeMode != WriteMode.SYNC) {
135                 writeMode = WriteMode.ASYNC
136             }
137         }
138     }
139 }
140 
141 open class GetStateScope(
142     val state: AccessState
143 )
144 
145 class MutateStateScope(
146     val oldState: AccessState,
147     val newState: AccessState
148 ) : GetStateScope(newState)
149