Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8b3e27e authored by Hai Zhang's avatar Hai Zhang
Browse files

Use immutable collections.

The immutable collections (under immutable/) should be used for all
data structures used in the policy classes, whereas the Android
collection helpers (under collection/) should be used in the
compatibility layer classes, and when interacting with objects
directly coming from in-process system APIs. The extension functions
for them added in this CL are more like boilterplates that we had to
add in order to make the methods calls happen on concrete classes
instead of interfaces, and to accommodate the SparseArray-like classes
that avoid autoboxing and thus can't have a uniform interface.

The access state classes have been refactored into immutable and
mutable types as well, similar to how the immutable collections
work. Thanks to the explicit mutations, manual calls to requestWrite()
is also no longer required and the compiler will ensure that we can
detect changes and know when to persist.

The policy classes are updated to follow the mutate*() pattern in
order to copy only the changing parts of the data structure. The
compatibility layer classes are updated to use the standard Android
collections directly, since it doesn't need immutability.

Some small refactoring also happened for some persistence, migration
and upgrade code, for them to be better organized/more consistent.

Bug: 182523293
Test: build
Change-Id: I2879a937ee6606a2bd0bc0c521076550ea1b058b
parent c58566fc
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.server.SystemService
import com.android.server.appop.AppOpsCheckingServiceInterface
import com.android.server.permission.access.appop.AppOpService
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.permission.PermissionService
import com.android.server.pm.KnownPackages
import com.android.server.pm.PackageManagerLocal
@@ -72,7 +73,7 @@ class AccessCheckingService(context: Context) : SystemService(context) {
        userManagerService = UserManagerService.getInstance()
        systemConfig = SystemConfig.getInstance()

        val userIds = IntSet(userManagerService.userIdsIncludingPreCreated)
        val userIds = MutableIntSet(userManagerService.userIdsIncludingPreCreated)
        val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
        val knownPackages = packageManagerInternal.knownPackages
        val isLeanback = systemConfig.isLeanback
@@ -82,7 +83,7 @@ class AccessCheckingService(context: Context) : SystemService(context) {
        val permissionAllowlist = systemConfig.permissionAllowlist
        val implicitToSourcePermissions = systemConfig.implicitToSourcePermissions

        val state = AccessState()
        val state = MutableAccessState()
        policy.initialize(
            state, userIds, packageStates, disabledSystemPackageStates, knownPackages, isLeanback,
            configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist,
@@ -104,7 +105,7 @@ class AccessCheckingService(context: Context) : SystemService(context) {
        get() = PackageManager.FEATURE_LEANBACK in availableFeatures

    private val SystemConfig.privilegedPermissionAllowlistPackages: IndexedListSet<String>
        get() = IndexedListSet<String>().apply {
        get() = MutableIndexedListSet<String>().apply {
            this += "android"
            if (PackageManager.FEATURE_AUTOMOTIVE in availableFeatures) {
                // Note that SystemProperties.get(String, String) forces returning an empty string
@@ -117,14 +118,16 @@ class AccessCheckingService(context: Context) : SystemService(context) {
        }

    private val SystemConfig.implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
        get() = IndexedMap<String, IndexedListSet<String>>().apply {
        @Suppress("UNCHECKED_CAST")
        get() = MutableIndexedMap<String, MutableIndexedListSet<String>>().apply {
            splitPermissions.forEach { splitPermissionInfo ->
                val sourcePermissionName = splitPermissionInfo.splitPermission
                splitPermissionInfo.newPermissions.forEach { implicitPermissionName ->
                    getOrPut(implicitPermissionName) { IndexedListSet() } += sourcePermissionName
                }
                    getOrPut(implicitPermissionName) { MutableIndexedListSet() } +=
                        sourcePermissionName
                }
            }
        } as IndexedMap<String, IndexedListSet<String>>

    fun getDecision(subject: AccessUri, `object`: AccessUri): Int =
        getState {
@@ -222,7 +225,7 @@ class AccessCheckingService(context: Context) : SystemService(context) {
        get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates }

    private val PackageManagerInternal.knownPackages: IntMap<Array<String>>
        get() = IntMap<Array<String>>().apply {
        get() = MutableIntMap<Array<String>>().apply {
            this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames(
                KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM
            )
@@ -269,7 +272,7 @@ class AccessCheckingService(context: Context) : SystemService(context) {
        contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
        synchronized(stateLock) {
            val oldState = state
            val newState = oldState.copy()
            val newState = oldState.toMutable()
            MutateStateScope(oldState, newState).action()
            persistence.write(newState)
            state = newState
+15 −30
Original line number Diff line number Diff line
@@ -23,11 +23,13 @@ import android.os.SystemClock
import android.os.UserHandle
import android.util.AtomicFile
import android.util.Log
import android.util.SparseLongArray
import com.android.internal.annotations.GuardedBy
import com.android.internal.os.BackgroundThread
import com.android.modules.utils.BinaryXmlPullParser
import com.android.modules.utils.BinaryXmlSerializer
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.util.PermissionApex
import com.android.server.permission.access.util.parseBinaryXml
import com.android.server.permission.access.util.readWithReserveCopy
@@ -41,9 +43,9 @@ class AccessPersistence(
) {
    private val scheduleLock = Any()
    @GuardedBy("scheduleLock")
    private val pendingMutationTimesMillis = IntLongMap()
    private val pendingMutationTimesMillis = SparseLongArray()
    @GuardedBy("scheduleLock")
    private val pendingStates = IntMap<AccessState>()
    private val pendingStates = MutableIntMap<AccessState>()
    @GuardedBy("scheduleLock")
    private lateinit var writeHandler: WriteHandler

@@ -56,14 +58,14 @@ class AccessPersistence(
    /**
     * Reads the state either from the disk or migrate legacy data when the data files are missing.
     */
    fun read(state: AccessState) {
    fun read(state: MutableAccessState) {
        readSystemState(state)
        state.systemState.userIds.forEachIndexed { _, userId ->
            readUserState(state, userId)
        }
    }

    private fun readSystemState(state: AccessState) {
    private fun readSystemState(state: MutableAccessState) {
        val fileExists = systemFile.parse {
            // This is the canonical way to call an extension function in a different class.
            // TODO(b/259469752): Use context receiver for this when it becomes stable.
@@ -72,25 +74,18 @@ class AccessPersistence(

        if (!fileExists) {
            policy.migrateSystemState(state)
            state.systemState.apply {
                requestWrite()
                write(state, UserHandle.USER_ALL)
            }
            state.systemState.write(state, UserHandle.USER_ALL)
        }
    }


    private fun readUserState(state: AccessState, userId: Int) {
    private fun readUserState(state: MutableAccessState, userId: Int) {
        val fileExists = getUserFile(userId).parse {
            with(policy) { parseUserState(state, userId) }
        }

        if (!fileExists) {
            policy.migrateUserState(state, userId)
            state.userStates[userId].apply {
                requestWrite()
                write(state, userId)
            }
            state.userStates[userId]!!.write(state, userId)
        }
    }

@@ -119,11 +114,7 @@ class AccessPersistence(
    private fun WritableState.write(state: AccessState, userId: Int) {
        when (val writeMode = writeMode) {
            WriteMode.NONE -> {}
            WriteMode.SYNC -> {
                synchronized(scheduleLock) { pendingStates[userId] = state }
                writePendingState(userId)
            }
            WriteMode.ASYNC -> {
            WriteMode.ASYNCHRONOUS -> {
                synchronized(scheduleLock) {
                    writeHandler.removeMessages(userId)
                    pendingStates[userId] = state
@@ -142,6 +133,10 @@ class AccessPersistence(
                    }
                }
            }
            WriteMode.SYNCHRONOUS -> {
                synchronized(scheduleLock) { pendingStates[userId] = state }
                writePendingState(userId)
            }
            else -> error(writeMode)
        }
    }
@@ -151,7 +146,7 @@ class AccessPersistence(
            val state: AccessState?
            synchronized(scheduleLock) {
                pendingMutationTimesMillis -= userId
                state = pendingStates.removeReturnOld(userId)
                state = pendingStates.remove(userId)
                writeHandler.removeMessages(userId)
            }
            if (state == null) {
@@ -201,16 +196,6 @@ class AccessPersistence(
    }

    private inner class WriteHandler(looper: Looper) : Handler(looper) {
        fun writeAtTime(userId: Int, timeMillis: Long) {
            removeMessages(userId)
            val message = obtainMessage(userId)
            sendMessageDelayed(message, timeMillis)
        }

        fun cancelWrite(userId: Int) {
            removeMessages(userId)
        }

        override fun handleMessage(message: Message) {
            val userId = message.what
            writePendingState(userId)
+94 −98
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import com.android.server.SystemConfig
import com.android.server.permission.access.appop.AppIdAppOpPolicy
import com.android.server.permission.access.appop.PackageAppOpPolicy
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.immutable.IndexedMap
import com.android.server.permission.access.permission.AppIdPermissionPolicy
import com.android.server.permission.access.util.attributeInt
import com.android.server.permission.access.util.attributeInterned
@@ -37,14 +39,16 @@ import com.android.server.pm.pkg.PackageState
class AccessPolicy private constructor(
    private val schemePolicies: IndexedMap<String, IndexedMap<String, SchemePolicy>>
) {
    @Suppress("UNCHECKED_CAST")
    constructor() : this(
        IndexedMap<String, IndexedMap<String, SchemePolicy>>().apply {
            fun addPolicy(policy: SchemePolicy) =
                getOrPut(policy.subjectScheme) { IndexedMap() }.put(policy.objectScheme, policy)
        MutableIndexedMap<String, MutableIndexedMap<String, SchemePolicy>>().apply {
            fun addPolicy(policy: SchemePolicy) {
                getOrPut(policy.subjectScheme) { MutableIndexedMap() }[policy.objectScheme] = policy
            }
            addPolicy(AppIdPermissionPolicy())
            addPolicy(AppIdAppOpPolicy())
            addPolicy(PackageAppOpPolicy())
        }
        } as IndexedMap<String, IndexedMap<String, SchemePolicy>>
    )

    fun getSchemePolicy(subjectScheme: String, objectScheme: String): SchemePolicy =
@@ -60,7 +64,7 @@ class AccessPolicy private constructor(
    }

    fun initialize(
        state: AccessState,
        state: MutableAccessState,
        userIds: IntSet,
        packageStates: Map<String, PackageState>,
        disabledSystemPackageStates: Map<String, PackageState>,
@@ -71,25 +75,23 @@ class AccessPolicy private constructor(
        permissionAllowlist: PermissionAllowlist,
        implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
    ) {
        state.systemState.apply {
            this.userIds += userIds
            this.packageStates = packageStates
            this.disabledSystemPackageStates = disabledSystemPackageStates
        state.mutateSystemState(WriteMode.NONE).apply {
            mutateUserIds() += userIds
            setPackageStates(packageStates)
            setDisabledSystemPackageStates(disabledSystemPackageStates)
            packageStates.forEach { (_, packageState) ->
                appIds.getOrPut(packageState.appId) { IndexedListSet() }
                mutateAppIds().mutateOrPut(packageState.appId) { MutableIndexedListSet() }
                    .add(packageState.packageName)
            }
            this.knownPackages = knownPackages
            this.isLeanback = isLeanback
            this.configPermissions = configPermissions
            this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages
            this.permissionAllowlist = permissionAllowlist
            this.implicitToSourcePermissions = implicitToSourcePermissions
        }
        state.userStates.apply {
            userIds.forEachIndexed { _, userId ->
                this[userId] = UserState()
            setKnownPackages(knownPackages)
            setLeanback(isLeanback)
            setConfigPermissions(configPermissions)
            setPrivilegedPermissionAllowlistPackages(privilegedPermissionAllowlistPackages)
            setPermissionAllowlist(permissionAllowlist)
            setImplicitToSourcePermissions(implicitToSourcePermissions)
        }
        state.mutateUserStatesNoWrite().apply {
            userIds.forEachIndexed { _, userId -> this[userId] = MutableUserState() }
        }
    }

@@ -106,8 +108,8 @@ class AccessPolicy private constructor(
    }

    fun MutateStateScope.onUserAdded(userId: Int) {
        newState.systemState.userIds += userId
        newState.userStates[userId] = UserState()
        newState.mutateSystemState(WriteMode.NONE).mutateUserIds() += userId
        newState.mutateUserStatesNoWrite()[userId] = MutableUserState()
        forEachSchemePolicy {
            with(it) { onUserAdded(userId) }
        }
@@ -117,8 +119,8 @@ class AccessPolicy private constructor(
    }

    fun MutateStateScope.onUserRemoved(userId: Int) {
        newState.systemState.userIds -= userId
        newState.userStates -= userId
        newState.mutateSystemState(WriteMode.NONE).mutateUserIds() -= userId
        newState.mutateUserStatesNoWrite() -= userId
        forEachSchemePolicy {
            with(it) { onUserRemoved(userId) }
        }
@@ -131,20 +133,20 @@ class AccessPolicy private constructor(
        volumeUuid: String?,
        isSystemUpdated: Boolean
    ) {
        val addedAppIds = IntSet()
        newState.systemState.apply {
            this.packageStates = packageStates
            this.disabledSystemPackageStates = disabledSystemPackageStates
        val addedAppIds = MutableIntSet()
        newState.mutateSystemState(WriteMode.NONE).apply {
            setPackageStates(packageStates)
            setDisabledSystemPackageStates(disabledSystemPackageStates)
            packageStates.forEach { (packageName, packageState) ->
                if (packageState.volumeUuid == volumeUuid) {
                    val appId = packageState.appId
                    appIds.getOrPut(appId) {
                    mutateAppIds().mutateOrPut(appId) {
                        addedAppIds += appId
                        IndexedListSet()
                        MutableIndexedListSet()
                    } += packageName
                }
            }
            this.knownPackages = knownPackages
            setKnownPackages(knownPackages)
        }
        addedAppIds.forEachIndexed { _, appId ->
            forEachSchemePolicy {
@@ -176,14 +178,14 @@ class AccessPolicy private constructor(
        }
        val appId = packageState.appId
        var isAppIdAdded = false
        newState.systemState.apply {
            this.packageStates = packageStates
            this.disabledSystemPackageStates = disabledSystemPackageStates
            appIds.getOrPut(appId) {
        newState.mutateSystemState(WriteMode.NONE).apply {
            setPackageStates(packageStates)
            setDisabledSystemPackageStates(disabledSystemPackageStates)
            mutateAppIds().mutateOrPut(appId) {
                isAppIdAdded = true
                IndexedListSet()
                MutableIndexedListSet()
            } += packageName
            this.knownPackages = knownPackages
            setKnownPackages(knownPackages)
        }
        if (isAppIdAdded) {
            forEachSchemePolicy {
@@ -210,17 +212,17 @@ class AccessPolicy private constructor(
            "Removed package $packageName is still in packageStates in onPackageRemoved()"
        }
        var isAppIdRemoved = false
        newState.systemState.apply {
            this.packageStates = packageStates
            this.disabledSystemPackageStates = disabledSystemPackageStates
            appIds[appId]?.apply {
        newState.mutateSystemState(WriteMode.NONE).apply {
            setPackageStates(packageStates)
            setDisabledSystemPackageStates(disabledSystemPackageStates)
            mutateAppIds().mutate(appId)?.apply {
                this -= packageName
                if (isEmpty()) {
                    appIds -= appId
                    mutateAppIds() -= appId
                    isAppIdRemoved = true
                }
            }
            this.knownPackages = knownPackages
            setKnownPackages(knownPackages)
        }
        forEachSchemePolicy {
            with(it) { onPackageRemoved(packageName, appId) }
@@ -230,9 +232,10 @@ class AccessPolicy private constructor(
                with(it) { onAppIdRemoved(appId) }
            }
        }
        newState.userStates.forEachIndexed { _, _, userState ->
            userState.packageVersions -= packageName
            userState.requestWrite()
        newState.userStates.forEachIndexed { userStateIndex, _, userState ->
            if (packageName in userState.packageVersions) {
                newState.mutateUserStateAt(userStateIndex).mutatePackageVersions() -= packageName
            }
        }
    }

@@ -243,10 +246,10 @@ class AccessPolicy private constructor(
        packageName: String,
        userId: Int
    ) {
        newState.systemState.apply {
            this.packageStates = packageStates
            this.disabledSystemPackageStates = disabledSystemPackageStates
            this.knownPackages = knownPackages
        newState.mutateSystemState(WriteMode.NONE).apply {
            setPackageStates(packageStates)
            setDisabledSystemPackageStates(disabledSystemPackageStates)
            setKnownPackages(knownPackages)
        }
        val packageState = packageStates[packageName]
        // TODO(zhanghai): STOPSHIP: Remove check before feature enable.
@@ -266,10 +269,10 @@ class AccessPolicy private constructor(
        appId: Int,
        userId: Int
    ) {
        newState.systemState.apply {
            this.packageStates = packageStates
            this.disabledSystemPackageStates = disabledSystemPackageStates
            this.knownPackages = knownPackages
        newState.mutateSystemState(WriteMode.NONE).apply {
            setPackageStates(packageStates)
            setDisabledSystemPackageStates(disabledSystemPackageStates)
            setKnownPackages(knownPackages)
        }
        forEachSchemePolicy {
            with(it) { onPackageUninstalled(packageName, appId, userId) }
@@ -277,19 +280,19 @@ class AccessPolicy private constructor(
    }

    fun MutateStateScope.onSystemReady() {
        newState.systemState.isSystemReady = true
        newState.mutateSystemState(WriteMode.NONE).setSystemReady(true)
        forEachSchemePolicy {
            with(it) { onSystemReady() }
        }
    }

    fun migrateSystemState(state: AccessState) {
    fun migrateSystemState(state: MutableAccessState) {
        forEachSchemePolicy {
            with(it) { migrateSystemState(state) }
        }
    }

    fun migrateUserState(state: AccessState, userId: Int) {
    fun migrateUserState(state: MutableAccessState, userId: Int) {
        forEachSchemePolicy {
            with(it) { migrateUserState(state, userId) }
        }
@@ -303,22 +306,17 @@ class AccessPolicy private constructor(
        val packageName = packageState.packageName
        // The version would be latest when the package is new to the system, e.g. newly
        // installed, first boot, or system apps added via OTA.
        val version = newState.userStates[userId].packageVersions[packageName]
        val version = newState.userStates[userId]!!.packageVersions[packageName]
        when {
            version == null -> {
                newState.userStates[userId].apply {
                    packageVersions[packageName] = VERSION_LATEST
                    requestWrite()
                }
            }
            version == null ->
                newState.mutateUserState(userId)!!.mutatePackageVersions()[packageName] =
                    VERSION_LATEST
            version < VERSION_LATEST -> {
                forEachSchemePolicy {
                    with(it) { upgradePackageState(packageState, userId, version) }
                }
                newState.userStates[userId].apply {
                    packageVersions[packageName] = VERSION_LATEST
                    requestWrite()
                }
                newState.mutateUserState(userId)!!.mutatePackageVersions()[packageName] =
                    VERSION_LATEST
            }
            version == VERSION_LATEST -> {}
            else -> Log.w(
@@ -328,7 +326,7 @@ class AccessPolicy private constructor(
        }
    }

    fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
    fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) {
        forEachTag {
            when (tagName) {
                TAG_ACCESS -> {
@@ -351,7 +349,7 @@ class AccessPolicy private constructor(
        }
    }

    fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
    fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
        forEachTag {
            when (tagName) {
                TAG_ACCESS -> {
@@ -376,33 +374,30 @@ class AccessPolicy private constructor(
        }
    }

    private fun BinaryXmlPullParser.parsePackageVersions(state: AccessState, userId: Int) {
        val userState = state.userStates[userId]
    private fun BinaryXmlPullParser.parsePackageVersions(state: MutableAccessState, userId: Int) {
        val userState = state.mutateUserState(userId, WriteMode.NONE)!!
        val packageVersions = userState.mutatePackageVersions()
        forEachTag {
            when (tagName) {
                TAG_PACKAGE -> parsePackageVersion(userState)
                else -> Log.w(
                    LOG_TAG,
                    "Ignoring unknown tag $name when parsing package versions for user $userId"
                )
                TAG_PACKAGE -> parsePackageVersion(packageVersions)
                else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing package versions")
            }
        }
        userState.packageVersions.retainAllIndexed { _, packageName, _ ->
            val hasPackage = packageName in state.systemState.packageStates
            if (!hasPackage) {
                Log.w(
                    LOG_TAG,
                    "Dropping unknown $packageName when parsing package versions for user $userId"
                )
        packageVersions.forEachReversedIndexed { packageVersionIndex, packageName, _ ->
            if (packageName !in state.systemState.packageStates) {
                Log.w(LOG_TAG, "Dropping unknown $packageName when parsing package versions")
                packageVersions.removeAt(packageVersionIndex)
                userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
            }
            hasPackage
        }
    }

    private fun BinaryXmlPullParser.parsePackageVersion(userState: UserState) {
    private fun BinaryXmlPullParser.parsePackageVersion(
        packageVersions: MutableIndexedMap<String, Int>
    ) {
        val packageName = getAttributeValueOrThrow(ATTR_NAME).intern()
        val version = getAttributeIntOrThrow(ATTR_VERSION)
        userState.packageVersions[packageName] = version
        packageVersions[packageName] = version
    }

    fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
@@ -410,14 +405,15 @@ class AccessPolicy private constructor(
            forEachSchemePolicy {
                with(it) { serializeUserState(state, userId) }
            }

            serializeVersions(state.userStates[userId])
            serializePackageVersions(state.userStates[userId]!!.packageVersions)
        }
    }

    private fun BinaryXmlSerializer.serializeVersions(userState: UserState) {
    private fun BinaryXmlSerializer.serializePackageVersions(
        packageVersions: IndexedMap<String, Int>
    ) {
        tag(TAG_PACKAGE_VERSIONS) {
            userState.packageVersions.forEachIndexed { _, packageName, version ->
            packageVersions.forEachIndexed { _, packageName, version ->
                tag(TAG_PACKAGE) {
                    attributeInterned(ATTR_NAME, packageName)
                    attributeInt(ATTR_VERSION, version)
@@ -430,8 +426,8 @@ class AccessPolicy private constructor(
        getSchemePolicy(subject.scheme, `object`.scheme)

    private inline fun forEachSchemePolicy(action: (SchemePolicy) -> Unit) {
        schemePolicies.forEachValueIndexed { _, objectSchemePolicies ->
            objectSchemePolicies.forEachValueIndexed { _, schemePolicy ->
        schemePolicies.forEachIndexed { _, _, objectSchemePolicies ->
            objectSchemePolicies.forEachIndexed { _, _, schemePolicy ->
                action(schemePolicy)
            }
        }
@@ -491,9 +487,9 @@ abstract class SchemePolicy {

    open fun MutateStateScope.onSystemReady() {}

    open fun migrateSystemState(state: AccessState) {}
    open fun migrateSystemState(state: MutableAccessState) {}

    open fun migrateUserState(state: AccessState, userId: Int) {}
    open fun migrateUserState(state: MutableAccessState, userId: Int) {}

    open fun MutateStateScope.upgradePackageState(
        packageState: PackageState,
@@ -501,11 +497,11 @@ abstract class SchemePolicy {
        version: Int
    ) {}

    open fun BinaryXmlPullParser.parseSystemState(state: AccessState) {}
    open fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) {}

    open fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {}

    open fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {}
    open fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {}

    open fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {}
}
+358 −89

File changed.

Preview size limit exceeded, changes collapsed.

+26 −6

File changed.

Preview size limit exceeded, changes collapsed.

Loading