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.immutable.* // 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 private typealias ExternalStateReference = MutableReference<ExternalState, MutableExternalState>
27 
28 private typealias SystemStateReference = MutableReference<SystemState, MutableSystemState>
29 
30 typealias UserStates = IntReferenceMap<UserState, MutableUserState>
31 
32 typealias MutableUserStates = MutableIntReferenceMap<UserState, MutableUserState>
33 
34 private typealias UserStatesReference = MutableReference<UserStates, MutableUserStates>
35 
36 sealed class AccessState(
37     internal val externalStateReference: ExternalStateReference,
38     internal val systemStateReference: SystemStateReference,
39     internal val userStatesReference: UserStatesReference
40 ) : Immutable<MutableAccessState> {
41     val externalState: ExternalState
42         get() = externalStateReference.get()
43 
44     val systemState: SystemState
45         get() = systemStateReference.get()
46 
47     val userStates: UserStates
48         get() = userStatesReference.get()
49 
toMutablenull50     override fun toMutable(): MutableAccessState = MutableAccessState(this)
51 }
52 
53 class MutableAccessState
54 private constructor(
55     externalStateReference: ExternalStateReference,
56     systemStateReference: SystemStateReference,
57     userStatesReference: UserStatesReference
58 ) : AccessState(externalStateReference, systemStateReference, userStatesReference) {
59     constructor() :
60         this(
61             ExternalStateReference(MutableExternalState()),
62             SystemStateReference(MutableSystemState()),
63             UserStatesReference(MutableUserStates())
64         )
65 
66     internal constructor(
67         accessState: AccessState
68     ) : this(
69         accessState.externalStateReference.toImmutable(),
70         accessState.systemStateReference.toImmutable(),
71         accessState.userStatesReference.toImmutable()
72     )
73 
74     fun mutateExternalState(): MutableExternalState = externalStateReference.mutate()
75 
76     fun mutateSystemState(writeMode: Int = WriteMode.ASYNCHRONOUS): MutableSystemState =
77         systemStateReference.mutate().apply { requestWriteMode(writeMode) }
78 
79     fun mutateUserStatesNoWrite(): MutableUserStates = userStatesReference.mutate()
80 
81     fun mutateUserState(userId: Int, writeMode: Int = WriteMode.ASYNCHRONOUS): MutableUserState? =
82         mutateUserStatesNoWrite().mutate(userId)?.apply { requestWriteMode(writeMode) }
83 
84     fun mutateUserStateAt(index: Int, writeMode: Int = WriteMode.ASYNCHRONOUS): MutableUserState =
85         mutateUserStatesNoWrite().mutateAt(index).apply { requestWriteMode(writeMode) }
86 }
87 
88 private typealias UserIdsReference = MutableReference<IntSet, MutableIntSet>
89 
90 typealias AppIdPackageNames = IntReferenceMap<IndexedListSet<String>, MutableIndexedListSet<String>>
91 
92 typealias MutableAppIdPackageNames =
93     MutableIntReferenceMap<IndexedListSet<String>, MutableIndexedListSet<String>>
94 
95 private typealias AppIdPackageNamesReference =
96     MutableReference<AppIdPackageNames, MutableAppIdPackageNames>
97 
98 sealed class ExternalState(
99     val userIdsReference: UserIdsReference,
100     packageStates: Map<String, PackageState>,
101     disabledSystemPackageStates: Map<String, PackageState>,
102     val appIdPackageNamesReference: AppIdPackageNamesReference,
103     knownPackages: IntMap<Array<String>>,
104     isLeanback: Boolean,
105     configPermissions: Map<String, SystemConfig.PermissionEntry>,
106     privilegedPermissionAllowlistPackages: IndexedListSet<String>,
107     permissionAllowlist: PermissionAllowlist,
108     implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
109     isSystemReady: Boolean
110 ) : Immutable<MutableExternalState> {
111     val userIds: IntSet
112         get() = userIdsReference.get()
113 
114     var packageStates: Map<String, PackageState> = packageStates
115         protected set
116 
117     var disabledSystemPackageStates: Map<String, PackageState> = disabledSystemPackageStates
118         protected set
119 
120     val appIdPackageNames: AppIdPackageNames
121         get() = appIdPackageNamesReference.get()
122 
123     var knownPackages: IntMap<Array<String>> = knownPackages
124         protected set
125 
126     var isLeanback: Boolean = isLeanback
127         protected set
128 
129     var configPermissions: Map<String, SystemConfig.PermissionEntry> = configPermissions
130         protected set
131 
132     var privilegedPermissionAllowlistPackages: IndexedListSet<String> =
133         privilegedPermissionAllowlistPackages
134         protected set
135 
136     var permissionAllowlist: PermissionAllowlist = permissionAllowlist
137         protected set
138 
139     var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> =
140         implicitToSourcePermissions
141         protected set
142 
143     var isSystemReady: Boolean = isSystemReady
144         protected set
145 
toMutablenull146     override fun toMutable(): MutableExternalState = MutableExternalState(this)
147 }
148 
149 class MutableExternalState
150 private constructor(
151     userIdsReference: UserIdsReference,
152     packageStates: Map<String, PackageState>,
153     disabledSystemPackageStates: Map<String, PackageState>,
154     appIdPackageNamesReference: AppIdPackageNamesReference,
155     knownPackages: IntMap<Array<String>>,
156     isLeanback: Boolean,
157     configPermissions: Map<String, SystemConfig.PermissionEntry>,
158     privilegedPermissionAllowlistPackages: IndexedListSet<String>,
159     permissionAllowlist: PermissionAllowlist,
160     implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
161     isSystemReady: Boolean
162 ) :
163     ExternalState(
164         userIdsReference,
165         packageStates,
166         disabledSystemPackageStates,
167         appIdPackageNamesReference,
168         knownPackages,
169         isLeanback,
170         configPermissions,
171         privilegedPermissionAllowlistPackages,
172         permissionAllowlist,
173         implicitToSourcePermissions,
174         isSystemReady
175     ) {
176     constructor() :
177         this(
178             UserIdsReference(MutableIntSet()),
179             emptyMap(),
180             emptyMap(),
181             AppIdPackageNamesReference(MutableAppIdPackageNames()),
182             MutableIntMap(),
183             false,
184             emptyMap(),
185             MutableIndexedListSet(),
186             PermissionAllowlist(),
187             MutableIndexedMap(),
188             false
189         )
190 
191     internal constructor(
192         externalState: ExternalState
193     ) : this(
194         externalState.userIdsReference.toImmutable(),
195         externalState.packageStates,
196         externalState.disabledSystemPackageStates,
197         externalState.appIdPackageNamesReference.toImmutable(),
198         externalState.knownPackages,
199         externalState.isLeanback,
200         externalState.configPermissions,
201         externalState.privilegedPermissionAllowlistPackages,
202         externalState.permissionAllowlist,
203         externalState.implicitToSourcePermissions,
204         externalState.isSystemReady
205     )
206 
207     fun mutateUserIds(): MutableIntSet = userIdsReference.mutate()
208 
209     @JvmName("setPackageStatesPublic")
210     fun setPackageStates(packageStates: Map<String, PackageState>) {
211         this.packageStates = packageStates
212     }
213 
214     @JvmName("setDisabledSystemPackageStatesPublic")
215     fun setDisabledSystemPackageStates(disabledSystemPackageStates: Map<String, PackageState>) {
216         this.disabledSystemPackageStates = disabledSystemPackageStates
217     }
218 
219     fun mutateAppIdPackageNames(): MutableAppIdPackageNames = appIdPackageNamesReference.mutate()
220 
221     @JvmName("setKnownPackagesPublic")
222     fun setKnownPackages(knownPackages: IntMap<Array<String>>) {
223         this.knownPackages = knownPackages
224     }
225 
226     @JvmName("setLeanbackPublic")
227     fun setLeanback(isLeanback: Boolean) {
228         this.isLeanback = isLeanback
229     }
230 
231     @JvmName("setConfigPermissionsPublic")
232     fun setConfigPermissions(configPermissions: Map<String, SystemConfig.PermissionEntry>) {
233         this.configPermissions = configPermissions
234     }
235 
236     @JvmName("setPrivilegedPermissionAllowlistPackagesPublic")
237     fun setPrivilegedPermissionAllowlistPackages(
238         privilegedPermissionAllowlistPackages: IndexedListSet<String>
239     ) {
240         this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages
241     }
242 
243     @JvmName("setPermissionAllowlistPublic")
244     fun setPermissionAllowlist(permissionAllowlist: PermissionAllowlist) {
245         this.permissionAllowlist = permissionAllowlist
246     }
247 
248     @JvmName("setImplicitToSourcePermissionsPublic")
249     fun setImplicitToSourcePermissions(
250         implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
251     ) {
252         this.implicitToSourcePermissions = implicitToSourcePermissions
253     }
254 
255     @JvmName("setSystemReadyPublic")
256     fun setSystemReady(isSystemReady: Boolean) {
257         this.isSystemReady = isSystemReady
258     }
259 }
260 
261 private typealias PermissionGroupsReference =
262     MutableReference<
263         IndexedMap<String, PermissionGroupInfo>, MutableIndexedMap<String, PermissionGroupInfo>
264     >
265 
266 private typealias PermissionTreesReference =
267     MutableReference<IndexedMap<String, Permission>, MutableIndexedMap<String, Permission>>
268 
269 private typealias PermissionsReference =
270     MutableReference<IndexedMap<String, Permission>, MutableIndexedMap<String, Permission>>
271 
272 sealed class SystemState(
273     val permissionGroupsReference: PermissionGroupsReference,
274     val permissionTreesReference: PermissionTreesReference,
275     val permissionsReference: PermissionsReference,
276     writeMode: Int
277 ) : WritableState, Immutable<MutableSystemState> {
278     val permissionGroups: IndexedMap<String, PermissionGroupInfo>
279         get() = permissionGroupsReference.get()
280 
281     val permissionTrees: IndexedMap<String, Permission>
282         get() = permissionTreesReference.get()
283 
284     val permissions: IndexedMap<String, Permission>
285         get() = permissionsReference.get()
286 
287     override var writeMode: Int = writeMode
288         protected set
289 
toMutablenull290     override fun toMutable(): MutableSystemState = MutableSystemState(this)
291 }
292 
293 class MutableSystemState
294 private constructor(
295     permissionGroupsReference: PermissionGroupsReference,
296     permissionTreesReference: PermissionTreesReference,
297     permissionsReference: PermissionsReference,
298     writeMode: Int
299 ) :
300     SystemState(
301         permissionGroupsReference,
302         permissionTreesReference,
303         permissionsReference,
304         writeMode
305     ),
306     MutableWritableState {
307     constructor() :
308         this(
309             PermissionGroupsReference(MutableIndexedMap()),
310             PermissionTreesReference(MutableIndexedMap()),
311             PermissionsReference(MutableIndexedMap()),
312             WriteMode.NONE
313         )
314 
315     internal constructor(
316         systemState: SystemState
317     ) : this(
318         systemState.permissionGroupsReference.toImmutable(),
319         systemState.permissionTreesReference.toImmutable(),
320         systemState.permissionsReference.toImmutable(),
321         WriteMode.NONE
322     )
323 
324     fun mutatePermissionGroups(): MutableIndexedMap<String, PermissionGroupInfo> =
325         permissionGroupsReference.mutate()
326 
327     fun mutatePermissionTrees(): MutableIndexedMap<String, Permission> =
328         permissionTreesReference.mutate()
329 
330     fun mutatePermissions(): MutableIndexedMap<String, Permission> = permissionsReference.mutate()
331 
332     override fun requestWriteMode(writeMode: Int) {
333         this.writeMode = maxOf(this.writeMode, writeMode)
334     }
335 }
336 
337 private typealias PackageVersionsReference =
338     MutableReference<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
339 
340 typealias AppIdPermissionFlags =
341     IntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
342 
343 typealias MutableAppIdPermissionFlags =
344     MutableIntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
345 
346 private typealias AppIdPermissionFlagsReference =
347     MutableReference<AppIdPermissionFlags, MutableAppIdPermissionFlags>
348 
349 typealias DevicePermissionFlags =
350     IndexedReferenceMap<String, IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
351 
352 typealias MutableDevicePermissionFlags =
353     MutableIndexedReferenceMap<String, IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
354 
355 typealias AppIdDevicePermissionFlags =
356     IntReferenceMap<DevicePermissionFlags, MutableDevicePermissionFlags>
357 
358 typealias MutableAppIdDevicePermissionFlags =
359     MutableIntReferenceMap<DevicePermissionFlags, MutableDevicePermissionFlags>
360 
361 private typealias AppIdDevicePermissionFlagsReference =
362     MutableReference<AppIdDevicePermissionFlags, MutableAppIdDevicePermissionFlags>
363 
364 typealias AppIdAppOpModes = IntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
365 
366 typealias MutableAppIdAppOpModes =
367     MutableIntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
368 
369 private typealias AppIdAppOpModesReference =
370     MutableReference<AppIdAppOpModes, MutableAppIdAppOpModes>
371 
372 typealias PackageAppOpModes =
373     IndexedReferenceMap<String, IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
374 
375 typealias MutablePackageAppOpModes =
376     MutableIndexedReferenceMap<String, IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
377 
378 private typealias PackageAppOpModesReference =
379     MutableReference<PackageAppOpModes, MutablePackageAppOpModes>
380 
381 sealed class UserState(
382     internal val packageVersionsReference: PackageVersionsReference,
383     internal val appIdPermissionFlagsReference: AppIdPermissionFlagsReference,
384     internal val appIdDevicePermissionFlagsReference: AppIdDevicePermissionFlagsReference,
385     internal val appIdAppOpModesReference: AppIdAppOpModesReference,
386     internal val packageAppOpModesReference: PackageAppOpModesReference,
387     defaultPermissionGrantFingerprint: String?,
388     writeMode: Int
389 ) : WritableState, Immutable<MutableUserState> {
390     val packageVersions: IndexedMap<String, Int>
391         get() = packageVersionsReference.get()
392 
393     val appIdPermissionFlags: AppIdPermissionFlags
394         get() = appIdPermissionFlagsReference.get()
395 
396     val appIdDevicePermissionFlags: AppIdDevicePermissionFlags
397         get() = appIdDevicePermissionFlagsReference.get()
398 
399     val appIdAppOpModes: AppIdAppOpModes
400         get() = appIdAppOpModesReference.get()
401 
402     val packageAppOpModes: PackageAppOpModes
403         get() = packageAppOpModesReference.get()
404 
405     var defaultPermissionGrantFingerprint: String? = defaultPermissionGrantFingerprint
406         protected set
407 
408     override var writeMode: Int = writeMode
409         protected set
410 
toMutablenull411     override fun toMutable(): MutableUserState = MutableUserState(this)
412 }
413 
414 class MutableUserState
415 private constructor(
416     packageVersionsReference: PackageVersionsReference,
417     appIdPermissionFlagsReference: AppIdPermissionFlagsReference,
418     appIdDevicePermissionFlagsReference: AppIdDevicePermissionFlagsReference,
419     appIdAppOpModesReference: AppIdAppOpModesReference,
420     packageAppOpModesReference: PackageAppOpModesReference,
421     defaultPermissionGrantFingerprint: String?,
422     writeMode: Int
423 ) :
424     UserState(
425         packageVersionsReference,
426         appIdPermissionFlagsReference,
427         appIdDevicePermissionFlagsReference,
428         appIdAppOpModesReference,
429         packageAppOpModesReference,
430         defaultPermissionGrantFingerprint,
431         writeMode
432     ),
433     MutableWritableState {
434     constructor() :
435         this(
436             PackageVersionsReference(MutableIndexedMap<String, Int>()),
437             AppIdPermissionFlagsReference(MutableAppIdPermissionFlags()),
438             AppIdDevicePermissionFlagsReference(MutableAppIdDevicePermissionFlags()),
439             AppIdAppOpModesReference(MutableAppIdAppOpModes()),
440             PackageAppOpModesReference(MutablePackageAppOpModes()),
441             null,
442             WriteMode.NONE
443         )
444 
445     internal constructor(
446         userState: UserState
447     ) : this(
448         userState.packageVersionsReference.toImmutable(),
449         userState.appIdPermissionFlagsReference.toImmutable(),
450         userState.appIdDevicePermissionFlagsReference.toImmutable(),
451         userState.appIdAppOpModesReference.toImmutable(),
452         userState.packageAppOpModesReference.toImmutable(),
453         userState.defaultPermissionGrantFingerprint,
454         WriteMode.NONE
455     )
456 
457     fun mutatePackageVersions(): MutableIndexedMap<String, Int> = packageVersionsReference.mutate()
458 
459     fun mutateAppIdPermissionFlags(): MutableAppIdPermissionFlags =
460         appIdPermissionFlagsReference.mutate()
461 
462     fun mutateAppIdDevicePermissionFlags(): MutableAppIdDevicePermissionFlags =
463         appIdDevicePermissionFlagsReference.mutate()
464 
465     fun mutateAppIdAppOpModes(): MutableAppIdAppOpModes = appIdAppOpModesReference.mutate()
466 
467     fun mutatePackageAppOpModes(): MutablePackageAppOpModes = packageAppOpModesReference.mutate()
468 
469     @JvmName("setDefaultPermissionGrantFingerprintPublic")
470     fun setDefaultPermissionGrantFingerprint(defaultPermissionGrantFingerprint: String?) {
471         this.defaultPermissionGrantFingerprint = defaultPermissionGrantFingerprint
472     }
473 
474     override fun requestWriteMode(writeMode: Int) {
475         this.writeMode = maxOf(this.writeMode, writeMode)
476     }
477 }
478 
479 object WriteMode {
480     const val NONE = 0
481     const val ASYNCHRONOUS = 1
482     const val SYNCHRONOUS = 2
483 }
484 
485 interface WritableState {
486     val writeMode: Int
487 }
488 
489 interface MutableWritableState : WritableState {
requestWriteModenull490     fun requestWriteMode(writeMode: Int)
491 }
492 
493 open class GetStateScope(val state: AccessState)
494 
495 class MutateStateScope(val oldState: AccessState, val newState: MutableAccessState) :
496     GetStateScope(newState)
497