1 /* 2 * 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.pm.permission; 18 19 import android.annotation.NonNull; 20 import android.content.pm.PackageManagerInternal; 21 import android.util.ArrayMap; 22 import android.util.Log; 23 24 import com.android.permission.persistence.RuntimePermissionsState; 25 import com.android.server.LocalManagerRegistry; 26 import com.android.server.LocalServices; 27 import com.android.server.pm.PackageManagerLocal; 28 import com.android.server.pm.pkg.PackageState; 29 import com.android.server.pm.pkg.SharedUserApi; 30 31 import java.util.List; 32 import java.util.Map; 33 34 /** 35 * Provider of legacy permissions data for new permission subsystem. 36 * 37 * @hide 38 */ 39 public class PermissionMigrationHelperImpl implements PermissionMigrationHelper { 40 private static final String LOG_TAG = PermissionMigrationHelperImpl.class.getSimpleName(); 41 42 @Override hasLegacyPermission()43 public boolean hasLegacyPermission() { 44 PackageManagerInternal packageManagerInternal = 45 LocalServices.getService(PackageManagerInternal.class); 46 LegacyPermissionSettings legacySettings = packageManagerInternal.getLegacyPermissions(); 47 return !(legacySettings.getPermissions().isEmpty() 48 && legacySettings.getPermissionTrees().isEmpty()); 49 } 50 51 /** 52 * @return legacy permission definitions. 53 */ 54 @NonNull getLegacyPermissions()55 public Map<String, LegacyPermission> getLegacyPermissions() { 56 PackageManagerInternal mPackageManagerInternal = 57 LocalServices.getService(PackageManagerInternal.class); 58 return toLegacyPermissions( 59 mPackageManagerInternal.getLegacyPermissions().getPermissions()); 60 } 61 62 /** 63 * @return legacy permission trees. 64 */ 65 @NonNull getLegacyPermissionTrees()66 public Map<String, LegacyPermission> getLegacyPermissionTrees() { 67 PackageManagerInternal mPackageManagerInternal = 68 LocalServices.getService(PackageManagerInternal.class); 69 return toLegacyPermissions( 70 mPackageManagerInternal.getLegacyPermissions().getPermissionTrees()); 71 } 72 73 @NonNull toLegacyPermissions( List<com.android.server.pm.permission.LegacyPermission> legacyPermissions)74 private Map<String, LegacyPermission> toLegacyPermissions( 75 List<com.android.server.pm.permission.LegacyPermission> legacyPermissions) { 76 Map<String, LegacyPermission> permissions = new ArrayMap<>(); 77 legacyPermissions.forEach(legacyPermission -> { 78 LegacyPermission permission = new LegacyPermission(legacyPermission.getPermissionInfo(), 79 legacyPermission.getType()); 80 permissions.put(legacyPermission.getPermissionInfo().name, permission); 81 }); 82 83 return permissions; 84 } 85 86 /** 87 * @return permissions state for a user, i.e. map of appId to map of permission name and state. 88 */ 89 @NonNull getLegacyPermissionStates(int userId)90 public Map<Integer, Map<String, LegacyPermissionState>> getLegacyPermissionStates(int userId) { 91 PackageManagerInternal mPackageManagerInternal = 92 LocalServices.getService(PackageManagerInternal.class); 93 Map<Integer, Map<String, LegacyPermissionState>> appIdPermissionStates = new ArrayMap<>(); 94 95 RuntimePermissionsState legacyState = 96 (RuntimePermissionsState) mPackageManagerInternal.getLegacyPermissionsState(userId); 97 PackageManagerLocal packageManagerLocal = 98 LocalManagerRegistry.getManager(PackageManagerLocal.class); 99 100 try (PackageManagerLocal.UnfilteredSnapshot snapshot = 101 packageManagerLocal.withUnfilteredSnapshot()) { 102 Map<String, PackageState> packageStates = snapshot.getPackageStates(); 103 legacyState.getPackagePermissions().forEach((packageName, permissionStates) -> { 104 if (!permissionStates.isEmpty()) { 105 PackageState packageState = packageStates.get(packageName); 106 if (packageState != null) { 107 int appId = packageState.getAppId(); 108 appIdPermissionStates.put(appId, 109 toLegacyPermissionStates(permissionStates)); 110 } else { 111 Log.w(LOG_TAG, "Package " + packageName + " not found."); 112 } 113 } 114 }); 115 116 Map<String, SharedUserApi> sharedUsers = snapshot.getSharedUsers(); 117 legacyState.getSharedUserPermissions().forEach((sharedUserName, permissionStates) -> { 118 if (!permissionStates.isEmpty()) { 119 SharedUserApi sharedUser = sharedUsers.get(sharedUserName); 120 if (sharedUser != null) { 121 int appId = sharedUser.getAppId(); 122 appIdPermissionStates.put(appId, 123 toLegacyPermissionStates(permissionStates)); 124 } else { 125 Log.w(LOG_TAG, "Shared user " + sharedUserName + " not found."); 126 } 127 } 128 }); 129 } 130 return appIdPermissionStates; 131 } 132 133 @Override getLegacyPermissionStateVersion(int userId)134 public int getLegacyPermissionStateVersion(int userId) { 135 PackageManagerInternal packageManagerInternal = 136 LocalServices.getService(PackageManagerInternal.class); 137 int version = packageManagerInternal.getLegacyPermissionsVersion(userId); 138 // -1 No permission data available 139 // 0 runtime-permissions.xml exist w/o any version 140 switch (version) { 141 case -1: 142 return 0; 143 case 0: 144 return -1; 145 default: 146 return version; 147 } 148 } 149 150 @Override hasLegacyPermissionState(int userId)151 public boolean hasLegacyPermissionState(int userId) { 152 return getLegacyPermissionStateVersion(userId) > -1; 153 } 154 155 @NonNull toLegacyPermissionStates( List<RuntimePermissionsState.PermissionState> permissions)156 private Map<String, LegacyPermissionState> toLegacyPermissionStates( 157 List<RuntimePermissionsState.PermissionState> permissions) { 158 Map<String, LegacyPermissionState> legacyPermissions = new ArrayMap<>(); 159 160 final int size = permissions.size(); 161 for (int i = 0; i < size; i++) { 162 RuntimePermissionsState.PermissionState permState = permissions.get(i); 163 legacyPermissions.put(permState.getName(), new LegacyPermissionState( 164 permState.isGranted(), permState.getFlags())); 165 } 166 167 return legacyPermissions; 168 } 169 } 170