blob: 71c6bd4b9395e5507969d56a8cadf6a55b26e747 [file] [log] [blame]
/*
* Copyright (C) 2022 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.permission.access.permission
import android.content.pm.PermissionInfo
import android.util.Log
import com.android.modules.utils.BinaryXmlPullParser
import com.android.modules.utils.BinaryXmlSerializer
import com.android.permission.access.SystemState
import com.android.permission.access.collection.* // ktlint-disable no-wildcard-imports
import com.android.permission.access.data.Permission
import com.android.permission.access.util.attribute
import com.android.permission.access.util.attributeInt
import com.android.permission.access.util.attributeIntHex
import com.android.permission.access.util.attributeIntHexWithDefault
import com.android.permission.access.util.attributeInterned
import com.android.permission.access.util.forEachTag
import com.android.permission.access.util.getAttributeIntHexOrDefault
import com.android.permission.access.util.getAttributeIntHexOrThrow
import com.android.permission.access.util.getAttributeIntOrThrow
import com.android.permission.access.util.getAttributeValue
import com.android.permission.access.util.getAttributeValueOrThrow
import com.android.permission.access.util.tag
import com.android.permission.access.util.tagName
class UidPermissionPersistence {
fun BinaryXmlPullParser.parseSystemState(systemState: SystemState) {
when (tagName) {
TAG_PERMISSION_TREES -> parsePermissions(systemState.permissionTrees)
TAG_PERMISSIONS -> parsePermissions(systemState.permissions)
else -> {}
}
}
private fun BinaryXmlPullParser.parsePermissions(permissions: IndexedMap<String, Permission>) {
forEachTag {
when (val tagName = tagName) {
TAG_PERMISSION -> parsePermission(permissions)
else -> Log.w(LOG_TAG, "Ignoring unknown tag $tagName when parsing permissions")
}
}
}
private fun BinaryXmlPullParser.parsePermission(permissions: IndexedMap<String, Permission>) {
val name = getAttributeValueOrThrow(ATTR_NAME).intern()
@Suppress("DEPRECATION")
val permissionInfo = PermissionInfo().apply {
this.name = name
packageName = getAttributeValueOrThrow(ATTR_PACKAGE_NAME).intern()
protectionLevel = getAttributeIntHexOrThrow(ATTR_PROTECTION_LEVEL)
}
val type = getAttributeIntOrThrow(ATTR_TYPE)
when (type) {
Permission.TYPE_MANIFEST -> {}
Permission.TYPE_CONFIG -> {
Log.w(LOG_TAG, "Ignoring unexpected config permission $name")
return
}
Permission.TYPE_DYNAMIC -> {
permissionInfo.apply {
icon = getAttributeIntHexOrDefault(ATTR_ICON, 0)
nonLocalizedLabel = getAttributeValue(ATTR_LABEL)
}
}
else -> {
Log.w(LOG_TAG, "Ignoring permission $name with unknown type $type")
return
}
}
val permission = Permission(permissionInfo, false, type, 0)
permissions[name] = permission
}
fun BinaryXmlSerializer.serializeSystemState(systemState: SystemState) {
serializePermissions(TAG_PERMISSION_TREES, systemState.permissionTrees)
serializePermissions(TAG_PERMISSIONS, systemState.permissions)
}
private fun BinaryXmlSerializer.serializePermissions(
tagName: String,
permissions: IndexedMap<String, Permission>
) {
tag(tagName) {
permissions.forEachValueIndexed { _, it -> serializePermission(it) }
}
}
private fun BinaryXmlSerializer.serializePermission(permission: Permission) {
val type = permission.type
when (type) {
Permission.TYPE_MANIFEST, Permission.TYPE_DYNAMIC -> {}
Permission.TYPE_CONFIG -> return
else -> {
Log.w(LOG_TAG, "Skipping serializing permission $name with unknown type $type")
return
}
}
tag(TAG_PERMISSION) {
attributeInterned(ATTR_NAME, permission.name)
attributeInterned(ATTR_PACKAGE_NAME, permission.packageName)
attributeIntHex(ATTR_PROTECTION_LEVEL, permission.protectionLevel)
attributeInt(ATTR_TYPE, type)
if (type == Permission.TYPE_DYNAMIC) {
val permissionInfo = permission.permissionInfo
attributeIntHexWithDefault(ATTR_ICON, permissionInfo.icon, 0)
permissionInfo.nonLocalizedLabel?.toString()?.let { attribute(ATTR_LABEL, it) }
}
}
}
companion object {
private val LOG_TAG = UidPermissionPersistence::class.java.simpleName
private const val TAG_PERMISSION = "permission"
private const val TAG_PERMISSION_TREES = "permission-trees"
private const val TAG_PERMISSIONS = "permissions"
private const val ATTR_ICON = "icon"
private const val ATTR_LABEL = "label"
private const val ATTR_NAME = "name"
private const val ATTR_PACKAGE_NAME = "packageName"
private const val ATTR_PROTECTION_LEVEL = "protectionLevel"
private const val ATTR_TYPE = "type"
}
}