1 /* <lambda>null2 * Copyright (C) 2023 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.permission 18 19 import android.util.Slog 20 import com.android.modules.utils.BinaryXmlPullParser 21 import com.android.modules.utils.BinaryXmlSerializer 22 import com.android.server.permission.access.AccessState 23 import com.android.server.permission.access.DevicePermissionFlags 24 import com.android.server.permission.access.MutableAccessState 25 import com.android.server.permission.access.MutableAppIdDevicePermissionFlags 26 import com.android.server.permission.access.MutableDevicePermissionFlags 27 import com.android.server.permission.access.WriteMode 28 import com.android.server.permission.access.immutable.IndexedMap 29 import com.android.server.permission.access.immutable.MutableIndexedMap 30 import com.android.server.permission.access.immutable.forEachIndexed 31 import com.android.server.permission.access.immutable.forEachReversedIndexed 32 import com.android.server.permission.access.immutable.set 33 import com.android.server.permission.access.util.andInv 34 import com.android.server.permission.access.util.attributeInt 35 import com.android.server.permission.access.util.attributeInterned 36 import com.android.server.permission.access.util.forEachTag 37 import com.android.server.permission.access.util.getAttributeIntOrThrow 38 import com.android.server.permission.access.util.getAttributeValueOrThrow 39 import com.android.server.permission.access.util.hasBits 40 import com.android.server.permission.access.util.tag 41 import com.android.server.permission.access.util.tagName 42 43 class DevicePermissionPersistence { 44 fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) { 45 when (tagName) { 46 TAG_APP_ID_DEVICE_PERMISSIONS -> parseAppIdDevicePermissions(state, userId) 47 else -> {} 48 } 49 } 50 51 private fun BinaryXmlPullParser.parseAppIdDevicePermissions( 52 state: MutableAccessState, 53 userId: Int 54 ) { 55 val userState = state.mutateUserState(userId, WriteMode.NONE)!! 56 val appIdDevicePermissionFlags = userState.mutateAppIdDevicePermissionFlags() 57 forEachTag { 58 when (tagName) { 59 TAG_APP_ID -> parseAppId(appIdDevicePermissionFlags) 60 else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state") 61 } 62 } 63 64 appIdDevicePermissionFlags.forEachReversedIndexed { appIdIndex, appId, _ -> 65 if (appId !in state.externalState.appIdPackageNames) { 66 Slog.w(LOG_TAG, "Dropping unknown app ID $appId when parsing permission state") 67 appIdDevicePermissionFlags.removeAt(appIdIndex) 68 userState.requestWriteMode(WriteMode.ASYNCHRONOUS) 69 } 70 } 71 } 72 73 private fun BinaryXmlPullParser.parseAppId( 74 appIdPermissionFlags: MutableAppIdDevicePermissionFlags 75 ) { 76 val appId = getAttributeIntOrThrow(ATTR_ID) 77 val devicePermissionFlags = MutableDevicePermissionFlags() 78 appIdPermissionFlags[appId] = devicePermissionFlags 79 forEachTag { 80 when (tagName) { 81 TAG_DEVICE -> parseDevice(devicePermissionFlags) 82 else -> { 83 Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state") 84 } 85 } 86 } 87 } 88 89 private fun BinaryXmlPullParser.parseDevice( 90 deviceIdPermissionFlags: MutableDevicePermissionFlags 91 ) { 92 val deviceId = getAttributeValueOrThrow(ATTR_ID) 93 val permissionFlags = MutableIndexedMap<String, Int>() 94 deviceIdPermissionFlags.put(deviceId, permissionFlags) 95 forEachTag { 96 when (tagName) { 97 TAG_PERMISSION -> parsePermission(permissionFlags) 98 else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state") 99 } 100 } 101 } 102 103 private fun BinaryXmlPullParser.parsePermission( 104 permissionFlags: MutableIndexedMap<String, Int> 105 ) { 106 val name = getAttributeValueOrThrow(ATTR_NAME).intern() 107 val flags = getAttributeIntOrThrow(ATTR_FLAGS) 108 permissionFlags[name] = flags 109 } 110 111 fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) { 112 val appIdDevicePermissionFlags = state.userStates[userId]!!.appIdDevicePermissionFlags 113 tag(TAG_APP_ID_DEVICE_PERMISSIONS) { 114 appIdDevicePermissionFlags.forEachIndexed { _, appId, devicePermissionFlags -> 115 serializeAppId(appId, devicePermissionFlags) 116 } 117 } 118 } 119 120 private fun BinaryXmlSerializer.serializeAppId( 121 appId: Int, 122 devicePermissionFlags: DevicePermissionFlags 123 ) { 124 tag(TAG_APP_ID) { 125 attributeInt(ATTR_ID, appId) 126 devicePermissionFlags.forEachIndexed { _, deviceId, permissionFlags -> 127 serializeDevice(deviceId, permissionFlags) 128 } 129 } 130 } 131 132 private fun BinaryXmlSerializer.serializeDevice( 133 deviceId: String, 134 permissionFlags: IndexedMap<String, Int> 135 ) { 136 tag(TAG_DEVICE) { 137 attributeInterned(ATTR_ID, deviceId) 138 permissionFlags.forEachIndexed { _, name, flags -> serializePermission(name, flags) } 139 } 140 } 141 142 private fun BinaryXmlSerializer.serializePermission(name: String, flags: Int) { 143 tag(TAG_PERMISSION) { 144 attributeInterned(ATTR_NAME, name) 145 // Never serialize one-time permissions as granted. 146 val serializedFlags = 147 if (flags.hasBits(PermissionFlags.ONE_TIME)) { 148 flags andInv PermissionFlags.RUNTIME_GRANTED 149 } else { 150 flags 151 } 152 attributeInt(ATTR_FLAGS, serializedFlags) 153 } 154 } 155 156 companion object { 157 private val LOG_TAG = DevicePermissionPersistence::class.java.simpleName 158 159 private const val TAG_APP_ID_DEVICE_PERMISSIONS = "app-id-device-permissions" 160 private const val TAG_APP_ID = "app-id" 161 private const val TAG_DEVICE = "device" 162 private const val TAG_PERMISSION = "permission" 163 164 private const val ATTR_ID = "id" 165 private const val ATTR_NAME = "name" 166 private const val ATTR_FLAGS = "flags" 167 } 168 } 169