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.server.LocalServices 21 import com.android.server.permission.access.MutableAccessState 22 import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports 23 import com.android.server.permission.access.util.PackageVersionMigration 24 import com.android.server.pm.permission.PermissionMigrationHelper 25 26 /** This class migrate legacy permissions to unified permission subsystem */ 27 class AppIdPermissionMigration { 28 internal fun migrateSystemState(state: MutableAccessState) { 29 val legacyPermissionsManager = 30 LocalServices.getService(PermissionMigrationHelper::class.java)!! 31 if (!legacyPermissionsManager.hasLegacyPermission()) { 32 return 33 } 34 35 migratePermissions( 36 state.mutateSystemState().mutatePermissions(), 37 legacyPermissionsManager.legacyPermissions 38 ) 39 migratePermissions( 40 state.mutateSystemState().mutatePermissionTrees(), 41 legacyPermissionsManager.legacyPermissionTrees, 42 true 43 ) 44 } 45 46 private fun migratePermissions( 47 permissions: MutableIndexedMap<String, Permission>, 48 legacyPermissions: Map<String, PermissionMigrationHelper.LegacyPermission>, 49 isPermissionTree: Boolean = false 50 ) { 51 legacyPermissions.forEach { (_, legacyPermission) -> 52 val permission = 53 Permission(legacyPermission.permissionInfo, false, legacyPermission.type, 0) 54 permissions[permission.name] = permission 55 if (DEBUG_MIGRATION) { 56 Slog.v( 57 LOG_TAG, 58 "Migrated permission: ${permission.name}, type: " + 59 "${permission.type}, appId: ${permission.appId}, protectionLevel: " + 60 "${permission.protectionLevel}, tree: $isPermissionTree" 61 ) 62 } 63 } 64 } 65 66 internal fun migrateUserState(state: MutableAccessState, userId: Int) { 67 val permissionMigrationHelper = 68 LocalServices.getService(PermissionMigrationHelper::class.java)!! 69 if (!permissionMigrationHelper.hasLegacyPermissionState(userId)) { 70 return 71 } 72 73 val legacyAppIdPermissionStates = 74 permissionMigrationHelper.getLegacyPermissionStates(userId) 75 val version = PackageVersionMigration.getVersion(userId) 76 77 val userState = state.mutateUserState(userId)!! 78 val appIdPermissionFlags = userState.mutateAppIdPermissionFlags() 79 legacyAppIdPermissionStates.forEach { (appId, legacyPermissionStates) -> 80 val packageNames = state.externalState.appIdPackageNames[appId] 81 if (packageNames == null) { 82 Slog.w(LOG_TAG, "Dropping unknown app ID $appId when migrating permission state") 83 return@forEach 84 } 85 86 val permissionFlags = MutableIndexedMap<String, Int>() 87 appIdPermissionFlags[appId] = permissionFlags 88 legacyPermissionStates.forEach forEachPermission@{ 89 (permissionName, legacyPermissionState) -> 90 val permission = state.systemState.permissions[permissionName] 91 if (permission == null) { 92 Slog.w( 93 LOG_TAG, 94 "Dropping unknown permission $permissionName for app ID $appId" + 95 " when migrating permission state" 96 ) 97 return@forEachPermission 98 } 99 permissionFlags[permissionName] = 100 migratePermissionFlags(permission, legacyPermissionState, appId, userId) 101 } 102 103 val packageVersions = userState.mutatePackageVersions() 104 packageNames.forEachIndexed { _, packageName -> packageVersions[packageName] = version } 105 } 106 } 107 108 private fun migratePermissionFlags( 109 permission: Permission, 110 legacyPermissionState: PermissionMigrationHelper.LegacyPermissionState, 111 appId: Int, 112 userId: Int 113 ): Int { 114 var flags = 115 when { 116 permission.isNormal -> 117 if (legacyPermissionState.isGranted) { 118 PermissionFlags.INSTALL_GRANTED 119 } else { 120 PermissionFlags.INSTALL_REVOKED 121 } 122 permission.isSignature || permission.isInternal -> 123 if (legacyPermissionState.isGranted) { 124 if (permission.isDevelopment || permission.isRole) { 125 PermissionFlags.PROTECTION_GRANTED or PermissionFlags.RUNTIME_GRANTED 126 } else { 127 PermissionFlags.PROTECTION_GRANTED 128 } 129 } else { 130 0 131 } 132 permission.isRuntime -> 133 if (legacyPermissionState.isGranted) PermissionFlags.RUNTIME_GRANTED else 0 134 else -> 0 135 } 136 flags = 137 PermissionFlags.updateFlags( 138 permission, 139 flags, 140 legacyPermissionState.flags, 141 legacyPermissionState.flags 142 ) 143 if (DEBUG_MIGRATION) { 144 val oldFlagString = PermissionFlags.apiFlagsToString(legacyPermissionState.flags) 145 val newFlagString = PermissionFlags.toString(flags) 146 val oldGrantState = legacyPermissionState.isGranted 147 val newGrantState = PermissionFlags.isPermissionGranted(flags) 148 val flagsMismatch = legacyPermissionState.flags != PermissionFlags.toApiFlags(flags) 149 Slog.v( 150 LOG_TAG, 151 "Migrated appId: $appId, permission: " + 152 "${permission.name}, user: $userId, oldGrantState: $oldGrantState" + 153 ", oldFlags: $oldFlagString, newFlags: $newFlagString, grantMismatch: " + 154 "${oldGrantState != newGrantState}, flagsMismatch: $flagsMismatch" 155 ) 156 } 157 return flags 158 } 159 160 companion object { 161 private val LOG_TAG = AppIdPermissionMigration::class.java.simpleName 162 163 private const val DEBUG_MIGRATION = false 164 } 165 } 166