1c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav/* 2c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Copyright (C) 2015 The Android Open Source Project 3c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 4c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Licensed under the Apache License, Version 2.0 (the "License"); 5c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * you may not use this file except in compliance with the License. 6c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * You may obtain a copy of the License at 7c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 8c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * http://www.apache.org/licenses/LICENSE-2.0 9c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 10c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Unless required by applicable law or agreed to in writing, software 11c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * distributed under the License is distributed on an "AS IS" BASIS, 12c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * See the License for the specific language governing permissions and 14c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * limitations under the License. 15c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 16c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 1782b0842051a93764e96a68072da1a220f00c2c27Todd Kennedypackage com.android.server.pm.permission; 18c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 199c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganovimport android.content.pm.PackageManager; 20c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport android.os.UserHandle; 21c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport android.util.ArrayMap; 22c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport android.util.ArraySet; 2300f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey 248c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganovimport android.util.SparseArray; 259c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganovimport android.util.SparseBooleanArray; 26c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport com.android.internal.util.ArrayUtils; 27c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 288c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganovimport java.util.ArrayList; 29c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport java.util.Arrays; 30c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport java.util.Collections; 318c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganovimport java.util.List; 32c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavimport java.util.Set; 33c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 34c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav/** 35c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * This class encapsulates the permissions for a package or a shared user. 36c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * <p> 37c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * There are two types of permissions: install (granted at installation) 38c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * and runtime (granted at runtime). Install permissions are granted to 39c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * all device users while runtime permissions are granted explicitly to 40c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * specific users. 41c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * </p> 42c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * <p> 43c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * The permissions are kept on a per device user basis. For example, an 44c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * application may have some runtime permissions granted under the device 45c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * owner but not granted under the secondary user. 46c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * <p> 47c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * This class is also responsible for keeping track of the Linux gids per 48c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * user for a package or a shared user. The gids are computed as a set of 49c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * the gids for all granted permissions' gids on a per user basis. 50c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * </p> 51c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 52c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslavpublic final class PermissionsState { 53c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 54b3f22b48bbd4e4816212e596e3cb612457d48fe5Svet Ganov /** The permission operation failed. */ 55b3f22b48bbd4e4816212e596e3cb612457d48fe5Svet Ganov public static final int PERMISSION_OPERATION_FAILURE = -1; 56b3f22b48bbd4e4816212e596e3cb612457d48fe5Svet Ganov 57c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** The permission operation succeeded and no gids changed. */ 58b3f22b48bbd4e4816212e596e3cb612457d48fe5Svet Ganov public static final int PERMISSION_OPERATION_SUCCESS = 0; 59c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 60c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** The permission operation succeeded and gids changed. */ 61b3f22b48bbd4e4816212e596e3cb612457d48fe5Svet Ganov public static final int PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED = 1; 62c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 63c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private static final int[] NO_GIDS = {}; 64c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 65c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private ArrayMap<String, PermissionData> mPermissions; 66c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 67c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private int[] mGlobalGids = NO_GIDS; 68c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 699c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov private SparseBooleanArray mPermissionReviewRequired; 709c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov 71c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public PermissionsState() { 72c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /* do nothing */ 73c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 74c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 75c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public PermissionsState(PermissionsState prototype) { 76c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav copyFrom(prototype); 77c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 78c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 79c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 80c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Sets the global gids, applicable to all users. 81c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 82c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param globalGids The global gids. 83c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 84c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public void setGlobalGids(int[] globalGids) { 85c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (!ArrayUtils.isEmpty(globalGids)) { 86c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mGlobalGids = Arrays.copyOf(globalGids, globalGids.length); 87c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 88c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 89c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 90c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 91c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Initialized this instance from another one. 92c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 93c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param other The other instance. 94c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 95c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public void copyFrom(PermissionsState other) { 964f2dcfd48010a338dc9a2f5870ed12b382c30cd7Svet Ganov if (other == this) { 974f2dcfd48010a338dc9a2f5870ed12b382c30cd7Svet Ganov return; 984f2dcfd48010a338dc9a2f5870ed12b382c30cd7Svet Ganov } 99c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (mPermissions != null) { 100c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (other.mPermissions == null) { 101c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mPermissions = null; 102c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } else { 103c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mPermissions.clear(); 104c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 105c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 106c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (other.mPermissions != null) { 107c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (mPermissions == null) { 108c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mPermissions = new ArrayMap<>(); 109c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 110c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int permissionCount = other.mPermissions.size(); 111c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav for (int i = 0; i < permissionCount; i++) { 112c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav String name = other.mPermissions.keyAt(i); 113c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav PermissionData permissionData = other.mPermissions.valueAt(i); 114c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mPermissions.put(name, new PermissionData(permissionData)); 115c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 116c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 117c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 118c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mGlobalGids = NO_GIDS; 119c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (other.mGlobalGids != NO_GIDS) { 120c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mGlobalGids = Arrays.copyOf(other.mGlobalGids, 121c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav other.mGlobalGids.length); 122c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 1239c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov 1249c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (mPermissionReviewRequired != null) { 1259c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (other.mPermissionReviewRequired == null) { 1269c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired = null; 1279c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } else { 1289c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired.clear(); 1299c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 1309c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 1319c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (other.mPermissionReviewRequired != null) { 1329c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (mPermissionReviewRequired == null) { 1339c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired = new SparseBooleanArray(); 1349c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 1359c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov final int userCount = other.mPermissionReviewRequired.size(); 1369c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov for (int i = 0; i < userCount; i++) { 1379c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov final boolean reviewRequired = other.mPermissionReviewRequired.valueAt(i); 1389c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired.put(i, reviewRequired); 1399c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 1409c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 1419c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 1429c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov 1433cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy @Override 1443cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy public boolean equals(Object obj) { 1453cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (this == obj) { 1463cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return true; 1473cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1483cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (obj == null) { 1493cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return false; 1503cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1513cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (getClass() != obj.getClass()) { 1523cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return false; 1533cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1543cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy final PermissionsState other = (PermissionsState) obj; 1553cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy 1563cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (mPermissions == null) { 1573cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (other.mPermissions != null) { 1583cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return false; 1593cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1603cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } else if (!mPermissions.equals(other.mPermissions)) { 1613cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return false; 1623cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1633cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (mPermissionReviewRequired == null) { 1643cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy if (other.mPermissionReviewRequired != null) { 1653cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return false; 1663cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1673cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } else if (!mPermissionReviewRequired.equals(other.mPermissionReviewRequired)) { 1683cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return false; 1693cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1703cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy return Arrays.equals(mGlobalGids, other.mGlobalGids); 1713cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy } 1723cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy 1739c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov public boolean isPermissionReviewRequired(int userId) { 1749c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov return mPermissionReviewRequired != null && mPermissionReviewRequired.get(userId); 175c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 176c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 177c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 178c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Grant an install permission. 179c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 180c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param permission The permission to grant. 181c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS}, 182c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link 183c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * #PERMISSION_OPERATION_FAILURE}. 184c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 185c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public int grantInstallPermission(BasePermission permission) { 186c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return grantPermission(permission, UserHandle.USER_ALL); 187c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 188c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 189c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 190c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Revoke an install permission. 191c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 192c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param permission The permission to revoke. 193c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS}, 194c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link 195c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * #PERMISSION_OPERATION_FAILURE}. 196c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 197c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public int revokeInstallPermission(BasePermission permission) { 198c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return revokePermission(permission, UserHandle.USER_ALL); 199c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 200c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 201c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 2028c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Grant a runtime permission for a given device user. 203c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 204c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param permission The permission to grant. 2058c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param userId The device user id. 206c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS}, 207c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link 208c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * #PERMISSION_OPERATION_FAILURE}. 209c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 210c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public int grantRuntimePermission(BasePermission permission, int userId) { 2118c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 212d5752bdc8fd39d4f0a508f9088c538e30e73044aSvet Ganov if (userId == UserHandle.USER_ALL) { 213d5752bdc8fd39d4f0a508f9088c538e30e73044aSvet Ganov return PERMISSION_OPERATION_FAILURE; 214d5752bdc8fd39d4f0a508f9088c538e30e73044aSvet Ganov } 215c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return grantPermission(permission, userId); 216c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 217c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 218c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 2198c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Revoke a runtime permission for a given device user. 220c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 221c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param permission The permission to revoke. 222c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param userId The device user id. 223c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS}, 224c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link 225c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * #PERMISSION_OPERATION_FAILURE}. 226c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 227c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public int revokeRuntimePermission(BasePermission permission, int userId) { 2288c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 229d5752bdc8fd39d4f0a508f9088c538e30e73044aSvet Ganov if (userId == UserHandle.USER_ALL) { 230d5752bdc8fd39d4f0a508f9088c538e30e73044aSvet Ganov return PERMISSION_OPERATION_FAILURE; 231d5752bdc8fd39d4f0a508f9088c538e30e73044aSvet Ganov } 232c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return revokePermission(permission, userId); 233c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 234c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 235c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 236c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Gets whether this state has a given runtime permission for a 237c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * given device user id. 238c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 239c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param name The permission name. 240c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param userId The device user id. 241c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return Whether this state has the permission. 242c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 243c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public boolean hasRuntimePermission(String name, int userId) { 2448c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 245c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return !hasInstallPermission(name) && hasPermission(name, userId); 246c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 247c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 248c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 249c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Gets whether this state has a given install permission. 250c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 251c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param name The permission name. 252c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return Whether this state has the permission. 253c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 254c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public boolean hasInstallPermission(String name) { 255c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return hasPermission(name, UserHandle.USER_ALL); 256c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 257c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 258c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 259c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Gets whether the state has a given permission for the specified 260c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * user, regardless if this is an install or a runtime permission. 261c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 262c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param name The permission name. 263c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param userId The device user id. 264c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return Whether the user has the permission. 265c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 266c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public boolean hasPermission(String name, int userId) { 267c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav enforceValidUserId(userId); 268c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 269c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (mPermissions == null) { 270c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return false; 271c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 272c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 273c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav PermissionData permissionData = mPermissions.get(name); 2748c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return permissionData != null && permissionData.isGranted(userId); 275c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 276c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 277c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 278ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn * Returns whether the state has any known request for the given permission name, 279ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn * whether or not it has been granted. 280ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn */ 281ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn public boolean hasRequestedPermission(ArraySet<String> names) { 282ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn if (mPermissions == null) { 283ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn return false; 284ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn } 285ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn for (int i=names.size()-1; i>=0; i--) { 286ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn if (mPermissions.get(names.valueAt(i)) != null) { 287ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn return true; 288ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn } 289ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn } 290ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn return false; 291ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn } 292ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn 293ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn /** 2948c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Gets all permissions for a given device user id regardless if they 2958c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * are install time or runtime permissions. 296c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 2978c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param userId The device user id. 298c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The permissions or an empty set. 299c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 3008c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public Set<String> getPermissions(int userId) { 3018c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 3028c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3038c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (mPermissions == null) { 3048c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return Collections.emptySet(); 305c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 306c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 3075e57a20c09512c676bc1ac938c5a2516ba260f72Fyodor Kupolov Set<String> permissions = new ArraySet<>(mPermissions.size()); 3088c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3098c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov final int permissionCount = mPermissions.size(); 3108c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov for (int i = 0; i < permissionCount; i++) { 3118c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov String permission = mPermissions.keyAt(i); 3128c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3138c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (hasInstallPermission(permission)) { 3148c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov permissions.add(permission); 3155e57a20c09512c676bc1ac938c5a2516ba260f72Fyodor Kupolov continue; 3168c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3178c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3188c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userId != UserHandle.USER_ALL) { 3198c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (hasRuntimePermission(permission, userId)) { 3208c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov permissions.add(permission); 3218c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3228c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3238c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3248c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3258c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return permissions; 326c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 327c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 328c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 3298c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Gets the state for an install permission or null if no such. 330c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 3318c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param name The permission name. 3328c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @return The permission state. 3338c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov */ 3348c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public PermissionState getInstallPermissionState(String name) { 3358c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return getPermissionState(name, UserHandle.USER_ALL); 3368c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3378c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3388c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov /** 3398c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Gets the state for a runtime permission or null if no such. 3408c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * 3418c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param name The permission name. 342c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param userId The device user id. 3438c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @return The permission state. 344c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 3458c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public PermissionState getRuntimePermissionState(String name, int userId) { 3468c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 3478c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return getPermissionState(name, userId); 348c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 349c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 350c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 3518c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Gets all install permission states. 352c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 3538c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @return The permission states or an empty set. 354c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 3558c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public List<PermissionState> getInstallPermissionStates() { 3568c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return getPermissionStatesInternal(UserHandle.USER_ALL); 357c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 358c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 359c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 3608c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Gets all runtime permission states. 361c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 3628c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @return The permission states or an empty set. 3638c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov */ 3648c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public List<PermissionState> getRuntimePermissionStates(int userId) { 3658c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 3668c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return getPermissionStatesInternal(userId); 3678c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3688c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3698c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov /** 3708c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Gets the flags for a permission regardless if it is install or 3718c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * runtime permission. 3728c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * 3738c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param name The permission name. 3748c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @return The permission state or null if no such. 375c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 3768c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public int getPermissionFlags(String name, int userId) { 3778c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState installPermState = getInstallPermissionState(name); 3788c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (installPermState != null) { 3798c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return installPermState.getFlags(); 3808c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3818c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState runtimePermState = getRuntimePermissionState(name, userId); 3828c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (runtimePermState != null) { 3838c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return runtimePermState.getFlags(); 3848c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3858c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return 0; 3868c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 3878c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 3888c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov /** 3898c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * Update the flags associated with a given permission. 3908c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param permission The permission whose flags to update. 3918c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param userId The user for which to update. 3928c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param flagMask Mask for which flags to change. 3938c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @param flagValues New values for the mask flags. 3948c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov * @return Whether the permission flags changed. 3958c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov */ 3968c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean updatePermissionFlags(BasePermission permission, int userId, 3978c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov int flagMask, int flagValues) { 3988c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 3998c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 4008c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov final boolean mayChangeFlags = flagValues != 0 || flagMask != 0; 4018c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 4028c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (mPermissions == null) { 4038c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!mayChangeFlags) { 4048c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 4058c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 4068c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov ensurePermissionData(permission); 4078c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 4088c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 40991a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy PermissionData permissionData = mPermissions.get(permission.getName()); 4108c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (permissionData == null) { 4118c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!mayChangeFlags) { 4128c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 4138c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 4148c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov permissionData = ensurePermissionData(permission); 4158c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 4168c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 4179c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov final int oldFlags = permissionData.getFlags(userId); 4189c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov 4199c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov final boolean updated = permissionData.updateFlags(userId, flagMask, flagValues); 4209c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (updated) { 4219c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov final int newFlags = permissionData.getFlags(userId); 4229c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0 4239c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { 4249c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (mPermissionReviewRequired == null) { 4259c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired = new SparseBooleanArray(); 4269c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 4279c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired.put(userId, true); 4289c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } else if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0 4299c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0) { 430587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov if (mPermissionReviewRequired != null && !hasPermissionRequiringReview(userId)) { 4319c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired.delete(userId); 4329c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov if (mPermissionReviewRequired.size() <= 0) { 4339c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired = null; 4349c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 4359c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 4369c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 4379c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov } 4389c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov return updated; 439c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 440c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 441587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov private boolean hasPermissionRequiringReview(int userId) { 442587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov final int permissionCount = mPermissions.size(); 443587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov for (int i = 0; i < permissionCount; i++) { 444587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov final PermissionData permission = mPermissions.valueAt(i); 445587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov if ((permission.getFlags(userId) 446587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { 447587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov return true; 448587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov } 449587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov } 450587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov return false; 451587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov } 452587512a0cfc88ba2e114a30554fc232d9b2c5a4fSvet Ganov 4530bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani public boolean updatePermissionFlagsForAllPermissions( 4540bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani int userId, int flagMask, int flagValues) { 4550bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani enforceValidUserId(userId); 4560bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani 4570bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani if (mPermissions == null) { 4580bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani return false; 4590bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani } 4600bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani boolean changed = false; 4610bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani final int permissionCount = mPermissions.size(); 4620bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani for (int i = 0; i < permissionCount; i++) { 4630bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani PermissionData permissionData = mPermissions.valueAt(i); 4640bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani changed |= permissionData.updateFlags(userId, flagMask, flagValues); 4650bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani } 4660bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani return changed; 4670bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani } 4680bf8f7cc3982164a9e11ea4a25ed930e466f1dd8Amith Yamasani 469c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 470c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Compute the Linux gids for a given device user from the permissions 471c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * granted to this user. Note that these are computed to avoid additional 472c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * state as they are rarely accessed. 473c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 474c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @param userId The device user id. 475c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The gids for the device user. 476c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 477c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public int[] computeGids(int userId) { 478c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav enforceValidUserId(userId); 479c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 480c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav int[] gids = mGlobalGids; 481c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 482c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (mPermissions != null) { 483c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int permissionCount = mPermissions.size(); 484c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav for (int i = 0; i < permissionCount; i++) { 485c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav String permission = mPermissions.keyAt(i); 486c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (!hasPermission(permission, userId)) { 487c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav continue; 488c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 489c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav PermissionData permissionData = mPermissions.valueAt(i); 49000f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey final int[] permGids = permissionData.computeGids(userId); 491c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (permGids != NO_GIDS) { 492c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav gids = appendInts(gids, permGids); 493c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 494c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 495c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 496c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 497c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return gids; 498c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 499c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 500c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 501c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Compute the Linux gids for all device users from the permissions 502c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * granted to these users. 503c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * 504c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * @return The gids for all device users. 505c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 50691edde24ffa5d78df18bf752de88dfe2bc8c4119Jeff Sharkey public int[] computeGids(int[] userIds) { 507c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav int[] gids = mGlobalGids; 508c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 50991edde24ffa5d78df18bf752de88dfe2bc8c4119Jeff Sharkey for (int userId : userIds) { 510c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int[] userGids = computeGids(userId); 511c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav gids = appendInts(gids, userGids); 512c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 513c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 514c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return gids; 515c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 516c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 517c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav /** 518c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav * Resets the internal state of this object. 519c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav */ 520c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public void reset() { 521c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mGlobalGids = NO_GIDS; 522c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav mPermissions = null; 5239c165d76010d9f79f5cd71978742a335b6b8d1b4Svet Ganov mPermissionReviewRequired = null; 524c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 525c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 5268c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private PermissionState getPermissionState(String name, int userId) { 5271b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav if (mPermissions == null) { 5288c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return null; 5291b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav } 5308c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionData permissionData = mPermissions.get(name); 5318c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (permissionData == null) { 5328c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return null; 5338c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 5348c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return permissionData.getPermissionState(userId); 5358c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 5361b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav 5378c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private List<PermissionState> getPermissionStatesInternal(int userId) { 5388c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov enforceValidUserId(userId); 5398c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 5408c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (mPermissions == null) { 5418c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return Collections.emptyList(); 5421b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav } 5431b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav 5448c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov List<PermissionState> permissionStates = new ArrayList<>(); 5451b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav 5461b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav final int permissionCount = mPermissions.size(); 5471b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav for (int i = 0; i < permissionCount; i++) { 5488c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionData permissionData = mPermissions.valueAt(i); 5491b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav 5508c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState permissionState = permissionData.getPermissionState(userId); 5518c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (permissionState != null) { 5528c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov permissionStates.add(permissionState); 5531b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav } 5541b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav } 5551b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav 556ca8e6da41c6e63e3ed17eb461171f1ef2e1d29c6Dianne Hackborn return permissionStates; 5571b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav } 5581b7025f264fd811ab27470867f8e65eeebf092e9Svetoslav 559c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private int grantPermission(BasePermission permission, int userId) { 56091a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy if (hasPermission(permission.getName(), userId)) { 561c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_FAILURE; 562c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 563c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 564b3a6defec84ab1d420b049c575cb37b1151e095aSvetoslav final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId)); 565c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS; 566c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 5678c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionData permissionData = ensurePermissionData(permission); 568c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 5698c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!permissionData.grant(userId)) { 570c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_FAILURE; 571c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 572c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 573c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (hasGids) { 574c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int[] newGids = computeGids(userId); 575c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (oldGids.length != newGids.length) { 576c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; 577c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 578c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 579c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 580c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_SUCCESS; 581c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 582c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 583c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private int revokePermission(BasePermission permission, int userId) { 58491a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy final String permName = permission.getName(); 58591a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy if (!hasPermission(permName, userId)) { 586c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_FAILURE; 587c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 588c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 589b3a6defec84ab1d420b049c575cb37b1151e095aSvetoslav final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId)); 590c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS; 591c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 59291a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy PermissionData permissionData = mPermissions.get(permName); 593c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 5948c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!permissionData.revoke(userId)) { 595c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_FAILURE; 596c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 597c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 5988c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (permissionData.isDefault()) { 59991a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy ensureNoPermissionData(permName); 600c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 601c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 602c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (hasGids) { 603c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav final int[] newGids = computeGids(userId); 604c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (oldGids.length != newGids.length) { 605c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; 606c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 607c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 608c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 609c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return PERMISSION_OPERATION_SUCCESS; 610c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 611c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6123cd658e1a598e59738bc129c35eecf4cd0f20680Todd Kennedy // TODO: fix this to use arraycopy and append all ints in one go 613c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private static int[] appendInts(int[] current, int[] added) { 614c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (current != null && added != null) { 615c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav for (int guid : added) { 616c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav current = ArrayUtils.appendInt(current, guid); 617c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 618c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 619c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return current; 620c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 621c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 622c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private static void enforceValidUserId(int userId) { 623c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav if (userId != UserHandle.USER_ALL && userId < 0) { 624c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav throw new IllegalArgumentException("Invalid userId:" + userId); 625c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 626c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 627c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6288c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private PermissionData ensurePermissionData(BasePermission permission) { 62991a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy final String permName = permission.getName(); 6308c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (mPermissions == null) { 6318c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mPermissions = new ArrayMap<>(); 6328c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 63391a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy PermissionData permissionData = mPermissions.get(permName); 6348c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (permissionData == null) { 6358c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov permissionData = new PermissionData(permission); 63691a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy mPermissions.put(permName, permissionData); 6378c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 6388c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return permissionData; 6398c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 6408c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 6418c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private void ensureNoPermissionData(String name) { 6428c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (mPermissions == null) { 6438c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return; 6448c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 6458c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mPermissions.remove(name); 6468c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (mPermissions.isEmpty()) { 6478c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mPermissions = null; 6488c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 6498c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 6508c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 651c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav private static final class PermissionData { 65200f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey private final BasePermission mPerm; 6538c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private SparseArray<PermissionState> mUserStates = new SparseArray<>(); 654c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 65500f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey public PermissionData(BasePermission perm) { 65600f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey mPerm = perm; 657c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 658c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 659c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav public PermissionData(PermissionData other) { 66000f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey this(other.mPerm); 6618c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov final int otherStateCount = other.mUserStates.size(); 6628c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov for (int i = 0; i < otherStateCount; i++) { 6638c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov final int otherUserId = other.mUserStates.keyAt(i); 6648c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState otherState = other.mUserStates.valueAt(i); 6658c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mUserStates.put(otherUserId, new PermissionState(otherState)); 666c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 667c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 668c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 66900f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey public int[] computeGids(int userId) { 67000f3904629ef89192e061c1995801ef322fc0bcfJeff Sharkey return mPerm.computeGids(userId); 671c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 672c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6738c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean isGranted(int userId) { 6748c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (isInstallPermission()) { 6758c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov userId = UserHandle.USER_ALL; 676c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 677c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6788c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState userState = mUserStates.get(userId); 6798c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userState == null) { 6808c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 681c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 682c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6838c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return userState.mGranted; 684c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 685c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6868c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean grant(int userId) { 6878c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!isCompatibleUserId(userId)) { 688c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return false; 689c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 690c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6918c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (isGranted(userId)) { 6928c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 693c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 694c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 6958c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState userState = mUserStates.get(userId); 6968c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userState == null) { 69791a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy userState = new PermissionState(mPerm.getName()); 6988c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mUserStates.put(userId, userState); 6998c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7008c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7018c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov userState.mGranted = true; 702c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 703c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return true; 704c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 705c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 7068c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean revoke(int userId) { 7078c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!isCompatibleUserId(userId)) { 708c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return false; 709c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 710c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 7118c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!isGranted(userId)) { 7128c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 713c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 714c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 7158c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState userState = mUserStates.get(userId); 7168c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov userState.mGranted = false; 717c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 7188c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userState.isDefault()) { 7198c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mUserStates.remove(userId); 720c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 721c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav 722c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav return true; 723c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 7248c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7258c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public PermissionState getPermissionState(int userId) { 7268c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return mUserStates.get(userId); 7278c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7288c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7298c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public int getFlags(int userId) { 7308c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState userState = mUserStates.get(userId); 7318c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userState != null) { 7328c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return userState.mFlags; 7338c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7348c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return 0; 7358c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7368c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7378c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean isDefault() { 7388c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return mUserStates.size() <= 0; 7398c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7408c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7418c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public static boolean isInstallPermissionKey(int userId) { 7428c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return userId == UserHandle.USER_ALL; 7438c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7448c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7458c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean updateFlags(int userId, int flagMask, int flagValues) { 7468c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (isInstallPermission()) { 7478c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov userId = UserHandle.USER_ALL; 7488c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7498c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7508c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (!isCompatibleUserId(userId)) { 7518c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 7528c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7538c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7548c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov final int newFlags = flagValues & flagMask; 7558c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7568c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov PermissionState userState = mUserStates.get(userId); 7578c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userState != null) { 7588c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov final int oldFlags = userState.mFlags; 7598c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov userState.mFlags = (userState.mFlags & ~flagMask) | newFlags; 7608c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov if (userState.isDefault()) { 7618c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mUserStates.remove(userId); 7628c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7638c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return userState.mFlags != oldFlags; 7648c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } else if (newFlags != 0) { 76591a39d126d1f6efa47948ca1039ca347c1bd19e6Todd Kennedy userState = new PermissionState(mPerm.getName()); 7668c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov userState.mFlags = newFlags; 7678c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mUserStates.put(userId, userState); 7688c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return true; 7698c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7708c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7718c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return false; 7728c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7738c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7748c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private boolean isCompatibleUserId(int userId) { 7758c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return isDefault() || !(isInstallPermission() ^ isInstallPermissionKey(userId)); 7768c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7778c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7788c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private boolean isInstallPermission() { 7798c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return mUserStates.size() == 1 7808c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov && mUserStates.get(UserHandle.USER_ALL) != null; 7818c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7828c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7838c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7848c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public static final class PermissionState { 7858c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private final String mName; 7868c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private boolean mGranted; 7878c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov private int mFlags; 7888c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7898c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public PermissionState(String name) { 7908c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mName = name; 7918c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7928c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7938c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public PermissionState(PermissionState other) { 7948c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mName = other.mName; 7958c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mGranted = other.mGranted; 7968c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov mFlags = other.mFlags; 7978c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 7988c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 7998c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean isDefault() { 8008c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return !mGranted && mFlags == 0; 8018c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 8028c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 8038c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public String getName() { 8048c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return mName; 8058c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 8068c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 8078c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public boolean isGranted() { 8088c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return mGranted; 8098c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 8108c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov 8118c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov public int getFlags() { 8128c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov return mFlags; 8138c7f700a59ad26e75c9791335d78f14322cad49aSvet Ganov } 814c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav } 815c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav} 816