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

Commit f94a1032 authored by Nate Myren's avatar Nate Myren
Browse files

Add IntIntMap for AppFunctionAccess policy

This will allow us to avoid boxing of Ints

Flag: android.permission.flags.app_function_access_service_enabled
Bug: 413093675
Test: AppIdAppFunctionAccessPolicyTest
Change-Id: I553a19bcc1aaca790803e2b0ad9c5fb604fbb643
parent a3cac0b7
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -361,11 +361,9 @@ typealias MutableAppIdPermissionFlags =
private typealias AppIdPermissionFlagsReference =
    MutableReference<AppIdPermissionFlags, MutableAppIdPermissionFlags>

// TODO b/413093675: create IntInt map
typealias AppIdAppFunctionAccessFlags = IntReferenceMap<IntMap<Int>, MutableIntMap<Int>>
typealias AppIdAppFunctionAccessFlags = IntReferenceMap<IntIntMap, MutableIntIntMap>

typealias MutableAppIdAppFunctionAccessFlags =
    MutableIntReferenceMap<IntMap<Int>, MutableIntMap<Int>>
typealias MutableAppIdAppFunctionAccessFlags = MutableIntReferenceMap<IntIntMap, MutableIntIntMap>

private typealias AppIdAppFunctionAccessFlagsReference =
    MutableReference<AppIdAppFunctionAccessFlags, MutableAppIdAppFunctionAccessFlags>
+3 −3
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ class AppIdAppFunctionAccessPersistence {
        appIdAppFunctionAccessFlags: MutableAppIdAppFunctionAccessFlags
    ) {
        val appId = getAttributeIntOrThrow(ATTR_ID)
        val appFunctionAccessFlags = MutableIntMap<Int>()
        val appFunctionAccessFlags = MutableIntIntMap()
        appIdAppFunctionAccessFlags.put(appId, appFunctionAccessFlags)
        forEachTag {
            when (tagName) {
@@ -109,7 +109,7 @@ class AppIdAppFunctionAccessPersistence {
    }

    private fun BinaryXmlPullParser.parseAppFunctionAccess(
        appFunctionAccessFlags: MutableIntMap<Int>
        appFunctionAccessFlags: MutableIntIntMap
    ) {
        val targetUid = getAttributeIntOrThrow(ATTR_TARGET_UID)
        val flags = getAttributeIntOrThrow(ATTR_FLAGS)
@@ -130,7 +130,7 @@ class AppIdAppFunctionAccessPersistence {
        }
    }

    private fun BinaryXmlSerializer.serializeAppId(appId: Int, accessFlags: IntMap<Int>) {
    private fun BinaryXmlSerializer.serializeAppId(appId: Int, accessFlags: IntIntMap) {
        tag(TAG_APP_ID) {
            attributeInt(ATTR_ID, appId)
            accessFlags.forEachIndexed { _, targetUid, flags ->
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ class AppIdAppFunctionAccessPolicy : SchemePolicy() {
        }
        val appIdAppFunctionAccessFlags =
            newState.mutateUserState(agentUserId)!!.mutateAppIdAppFunctionAccessFlags()
        val flags = appIdAppFunctionAccessFlags.mutateOrPut(agentAppId) { MutableIntMap() }
        val flags = appIdAppFunctionAccessFlags.mutateOrPut(agentAppId) { MutableIntIntMap() }
        flags.putWithDefault(targetUid, newFlags, 0)
        return true
    }
+92 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.permission.access.immutable

import android.util.SparseIntArray

/** Immutable map with indexed-base access, [Int] keys, and [Int] values */
sealed class IntIntMap(internal val array: SparseIntArray) : Immutable<MutableIntIntMap> {
    val size: Int
        get() = array.size()

    fun isEmpty(): Boolean = array.size() == 0

    operator fun contains(key: Int): Boolean = array.indexOfKey(key) >= 0

    operator fun get(key: Int): Int? = array.get(key)

    fun indexOfKey(key: Int): Int = array.indexOfKey(key)

    fun keyAt(index: Int): Int = array.keyAt(index)

    fun valueAt(index: Int): Int = array.valueAt(index)

    override fun toMutable(): MutableIntIntMap = MutableIntIntMap(this)

    override fun toString(): String = array.toString()
}

/** Mutable map with indexed-base access, [Int] keys, and [Int] values */
class MutableIntIntMap(array: SparseIntArray = SparseIntArray()) : IntIntMap(array) {
    constructor(intMap: IntIntMap) : this(intMap.array.clone())

    fun put(key: Int, value: Int): Int? = array.putReturnOld(key, value)

    fun remove(key: Int): Int? = array.removeReturnOld(key)

    fun clear() {
        array.clear()
    }

    fun putAt(index: Int, value: Int): Int = array.setValueAtReturnOld(index, value)

    fun removeAt(index: Int): Int = array.removeAtReturnOld(index)
}

internal fun SparseIntArray.putReturnOld(key: Int, value: Int): Int? {
    val index = indexOfKey(key)
    return if (index >= 0) {
        val oldValue = valueAt(index)
        setValueAt(index, value)
        oldValue
    } else {
        put(key, value)
        null
    }
}

internal fun SparseIntArray.removeReturnOld(key: Int): Int? {
    val index = indexOfKey(key)
    return if (index >= 0) {
        val oldValue = valueAt(index)
        removeAt(index)
        oldValue
    } else {
        null
    }
}

internal fun SparseIntArray.setValueAtReturnOld(index: Int, value: Int): Int {
    val oldValue = valueAt(index)
    setValueAt(index, value)
    return oldValue
}

internal fun SparseIntArray.removeAtReturnOld(index: Int): Int {
    val oldValue = valueAt(index)
    removeAt(index)
    return oldValue
}
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.permission.access.immutable

inline fun IntIntMap.allIndexed(predicate: (Int, Int, Int) -> Boolean): Boolean {
    forEachIndexed { index, key, value ->
        if (!predicate(index, key, value)) {
            return false
        }
    }
    return true
}

inline fun IntIntMap.anyIndexed(predicate: (Int, Int, Int) -> Boolean): Boolean {
    forEachIndexed { index, key, value ->
        if (predicate(index, key, value)) {
            return true
        }
    }
    return false
}

inline fun <R> IntIntMap.firstNotNullOfOrNullIndexed(transform: (Int, Int, Int) -> R): R? {
    forEachIndexed { index, key, value ->
        transform(index, key, value)?.let {
            return it
        }
    }
    return null
}

inline fun IntIntMap.forEachIndexed(action: (Int, Int, Int) -> Unit) {
    for (index in 0 until size) {
        action(index, keyAt(index), valueAt(index))
    }
}

inline fun IntIntMap.forEachReversedIndexed(action: (Int, Int, Int) -> Unit) {
    for (index in lastIndex downTo 0) {
        action(index, keyAt(index), valueAt(index))
    }
}

fun IntIntMap?.getWithDefault(key: Int, defaultValue: Int): Int {
    this ?: return defaultValue
    val index = indexOfKey(key)
    return if (index >= 0) valueAt(index) else defaultValue
}

inline val IntIntMap.lastIndex: Int
    get() = size - 1

inline fun IntIntMap.noneIndexed(predicate: (Int, Int, Int) -> Boolean): Boolean {
    forEachIndexed { index, key, value ->
        if (predicate(index, key, value)) {
            return false
        }
    }
    return true
}

inline fun MutableIntIntMap.getOrPut(key: Int, defaultValue: () -> Int): Int {
    get(key)?.let {
        return it
    }
    return defaultValue().also { put(key, it) }
}

operator fun MutableIntIntMap.minusAssign(key: Int) {
    array.delete(key)
}

fun MutableIntIntMap.putWithDefault(key: Int, value: Int, defaultValue: Int): Int {
    val index = indexOfKey(key)
    if (index >= 0) {
        val oldValue = valueAt(index)
        if (value != oldValue) {
            if (value == defaultValue) {
                removeAt(index)
            } else {
                putAt(index, value)
            }
        }
        return oldValue
    } else {
        if (value != defaultValue) {
            put(key, value)
        }
        return defaultValue
    }
}

operator fun MutableIntIntMap.set(key: Int, value: Int) {
    array.put(key, value)
}
Loading