1 /*
2  * Copyright (C) 2017 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.annotation.Nullable;
21 import com.android.server.pm.pkg.component.ParsedPermissionGroup;
22 import android.util.ArrayMap;
23 import android.util.ArraySet;
24 
25 import java.util.Collection;
26 
27 /**
28  * Permission registry for permissions, permission trees, permission groups and related things.
29  */
30 public class PermissionRegistry {
31     /**
32      * All of the permissions known to the system. The mapping is from permission
33      * name to permission object.
34      */
35     private final ArrayMap<String, Permission> mPermissions = new ArrayMap<>();
36 
37     /**
38      * All permission trees known to the system. The mapping is from permission tree
39      * name to permission object.
40      */
41     private final ArrayMap<String, Permission> mPermissionTrees = new ArrayMap<>();
42 
43     /**
44      * All permisson groups know to the system. The mapping is from permission group
45      * name to permission group object.
46      */
47     private final ArrayMap<String, ParsedPermissionGroup> mPermissionGroups = new ArrayMap<>();
48 
49     /**
50      * Set of packages that request a particular app op. The mapping is from permission
51      * name to package names.
52      */
53     private final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
54 
55     @NonNull
getPermissions()56     public Collection<Permission> getPermissions() {
57         return mPermissions.values();
58     }
59 
60     @Nullable
getPermission(@onNull String permissionName)61     public Permission getPermission(@NonNull String permissionName) {
62         return mPermissions.get(permissionName);
63     }
64 
addPermission(@onNull Permission permission)65     public void addPermission(@NonNull Permission permission) {
66         mPermissions.put(permission.getName(), permission);
67     }
68 
removePermission(@onNull String permissionName)69     public void removePermission(@NonNull String permissionName) {
70         mPermissions.remove(permissionName);
71     }
72 
73     @NonNull
getPermissionTrees()74     public Collection<Permission> getPermissionTrees() {
75         return mPermissionTrees.values();
76     }
77 
78     @Nullable
getPermissionTree(@onNull String permissionTreeName)79     public Permission getPermissionTree(@NonNull String permissionTreeName) {
80         return mPermissionTrees.get(permissionTreeName);
81     }
82 
addPermissionTree(@onNull Permission permissionTree)83     public void addPermissionTree(@NonNull Permission permissionTree) {
84         mPermissionTrees.put(permissionTree.getName(), permissionTree);
85     }
86 
87     /**
88      * Transfers ownership of permissions from one package to another.
89      */
transferPermissions(@onNull String oldPackageName, @NonNull String newPackageName)90     public void transferPermissions(@NonNull String oldPackageName,
91             @NonNull String newPackageName) {
92         for (int i = 0; i < 2; i++) {
93             ArrayMap<String, Permission> permissions = i == 0 ? mPermissionTrees : mPermissions;
94             for (final Permission permission : permissions.values()) {
95                 permission.transfer(oldPackageName, newPackageName);
96             }
97         }
98     }
99 
100     @NonNull
getPermissionGroups()101     public Collection<ParsedPermissionGroup> getPermissionGroups() {
102         return mPermissionGroups.values();
103     }
104 
105     @Nullable
getPermissionGroup(@onNull String permissionGroupName)106     public ParsedPermissionGroup getPermissionGroup(@NonNull String permissionGroupName) {
107         return mPermissionGroups.get(permissionGroupName);
108     }
109 
addPermissionGroup(@onNull ParsedPermissionGroup permissionGroup)110     public void addPermissionGroup(@NonNull ParsedPermissionGroup permissionGroup) {
111         mPermissionGroups.put(permissionGroup.getName(), permissionGroup);
112     }
113 
114     @NonNull
getAllAppOpPermissionPackages()115     public ArrayMap<String, ArraySet<String>> getAllAppOpPermissionPackages() {
116         return mAppOpPermissionPackages;
117     }
118 
119     @Nullable
getAppOpPermissionPackages(@onNull String permissionName)120     public ArraySet<String> getAppOpPermissionPackages(@NonNull String permissionName) {
121         return mAppOpPermissionPackages.get(permissionName);
122     }
123 
addAppOpPermissionPackage(@onNull String permissionName, @NonNull String packageName)124     public void addAppOpPermissionPackage(@NonNull String permissionName,
125             @NonNull String packageName) {
126         ArraySet<String> packageNames = mAppOpPermissionPackages.get(permissionName);
127         if (packageNames == null) {
128             packageNames = new ArraySet<>();
129             mAppOpPermissionPackages.put(permissionName, packageNames);
130         }
131         packageNames.add(packageName);
132     }
133 
removeAppOpPermissionPackage(@onNull String permissionName, @NonNull String packageName)134     public void removeAppOpPermissionPackage(@NonNull String permissionName,
135             @NonNull String packageName) {
136         final ArraySet<String> packageNames = mAppOpPermissionPackages.get(permissionName);
137         if (packageNames == null) {
138             return;
139         }
140         final boolean removed = packageNames.remove(packageName);
141         if (removed && packageNames.isEmpty()) {
142             mAppOpPermissionPackages.remove(permissionName);
143         }
144     }
145 
146     /**
147      * Returns the permission tree for the given permission.
148      * @throws SecurityException If the calling UID is not allowed to add permissions to the
149      * found permission tree.
150      */
151     @NonNull
enforcePermissionTree(@onNull String permissionName, int callingUid)152     public Permission enforcePermissionTree(@NonNull String permissionName, int callingUid) {
153         return Permission.enforcePermissionTree(mPermissionTrees.values(), permissionName,
154                 callingUid);
155     }
156 }
157