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 android.util.ArrayMap;
22 import android.util.ArraySet;
23 import android.util.Log;
24 
25 import com.android.internal.annotations.GuardedBy;
26 import com.android.internal.util.XmlUtils;
27 import com.android.modules.utils.TypedXmlPullParser;
28 import com.android.modules.utils.TypedXmlSerializer;
29 import com.android.server.pm.DumpState;
30 import com.android.server.pm.PackageManagerService;
31 import com.android.server.pm.PackageManagerTracedLock;
32 
33 import org.xmlpull.v1.XmlPullParser;
34 import org.xmlpull.v1.XmlPullParserException;
35 
36 import java.io.IOException;
37 import java.io.PrintWriter;
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 
43 /**
44  * Legacy permission settings for migration.
45  */
46 public class LegacyPermissionSettings {
47     /**
48      * All of the permissions known to the system. The mapping is from permission
49      * name to permission object.
50      */
51     @GuardedBy("mLock")
52     private final ArrayMap<String, LegacyPermission> mPermissions = new ArrayMap<>();
53 
54     /**
55      * All permission trees known to the system. The mapping is from permission tree
56      * name to permission object.
57      */
58     @GuardedBy("mLock")
59     private final ArrayMap<String, LegacyPermission> mPermissionTrees = new ArrayMap<>();
60 
61     @NonNull
62     private final PackageManagerTracedLock mLock = new PackageManagerTracedLock();
63 
64     @NonNull
getPermissions()65     public List<LegacyPermission> getPermissions() {
66         synchronized (mLock) {
67             return new ArrayList<>(mPermissions.values());
68         }
69     }
70 
71     @NonNull
getPermissionTrees()72     public List<LegacyPermission> getPermissionTrees() {
73         synchronized (mLock) {
74             return new ArrayList<>(mPermissionTrees.values());
75         }
76     }
77 
replacePermissions(@onNull List<LegacyPermission> permissions)78     public void replacePermissions(@NonNull List<LegacyPermission> permissions) {
79         synchronized (mLock) {
80             mPermissions.clear();
81             final int permissionsSize = permissions.size();
82             for (int i = 0; i < permissionsSize; i++) {
83                 final LegacyPermission permission = permissions.get(i);
84                 mPermissions.put(permission.getPermissionInfo().name, permission);
85             }
86         }
87     }
88 
replacePermissionTrees(@onNull List<LegacyPermission> permissionTrees)89     public void replacePermissionTrees(@NonNull List<LegacyPermission> permissionTrees) {
90         synchronized (mLock) {
91             mPermissionTrees.clear();
92             final int permissionsSize = permissionTrees.size();
93             for (int i = 0; i < permissionsSize; i++) {
94                 final LegacyPermission permissionTree = permissionTrees.get(i);
95                 mPermissionTrees.put(permissionTree.getPermissionInfo().name, permissionTree);
96             }
97         }
98     }
99 
readPermissions(@onNull TypedXmlPullParser parser)100     public void readPermissions(@NonNull TypedXmlPullParser parser) throws IOException,
101             XmlPullParserException {
102         synchronized (mLock) {
103             readPermissions(mPermissions, parser);
104         }
105     }
106 
readPermissionTrees(@onNull TypedXmlPullParser parser)107     public void readPermissionTrees(@NonNull TypedXmlPullParser parser) throws IOException,
108             XmlPullParserException {
109         synchronized (mLock) {
110             readPermissions(mPermissionTrees, parser);
111         }
112     }
113 
readPermissions(@onNull ArrayMap<String, LegacyPermission> out, @NonNull TypedXmlPullParser parser)114     public static void readPermissions(@NonNull ArrayMap<String, LegacyPermission> out,
115             @NonNull TypedXmlPullParser parser) throws IOException, XmlPullParserException {
116         int outerDepth = parser.getDepth();
117         int type;
118         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
119                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
120             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
121                 continue;
122             }
123 
124             if (!LegacyPermission.read(out, parser)) {
125                 PackageManagerService.reportSettingsProblem(Log.WARN,
126                         "Unknown element reading permissions: " + parser.getName() + " at "
127                                 + parser.getPositionDescription());
128             }
129             XmlUtils.skipCurrentTag(parser);
130         }
131     }
132 
writePermissions(@onNull TypedXmlSerializer serializer)133     public void writePermissions(@NonNull TypedXmlSerializer serializer) throws IOException {
134         synchronized (mLock) {
135             for (LegacyPermission bp : mPermissions.values()) {
136                 bp.write(serializer);
137             }
138         }
139     }
140 
writePermissionTrees(@onNull TypedXmlSerializer serializer)141     public void writePermissionTrees(@NonNull TypedXmlSerializer serializer) throws IOException {
142         synchronized (mLock) {
143             for (LegacyPermission bp : mPermissionTrees.values()) {
144                 bp.write(serializer);
145             }
146         }
147     }
148 
dumpPermissions(@onNull PrintWriter pw, @Nullable String packageName, @Nullable ArraySet<String> permissionNames, @NonNull List<LegacyPermission> permissions, @NonNull Map<String, Set<String>> appOpPermissionPackages, boolean externalStorageEnforced, @NonNull DumpState dumpState)149     public static void dumpPermissions(@NonNull PrintWriter pw, @Nullable String packageName,
150             @Nullable ArraySet<String> permissionNames, @NonNull List<LegacyPermission> permissions,
151             @NonNull Map<String, Set<String>> appOpPermissionPackages,
152             boolean externalStorageEnforced, @NonNull DumpState dumpState) {
153         boolean printedSomething = false;
154         final int permissionsSize = permissions.size();
155         for (int i = 0; i < permissionsSize; i++) {
156             final LegacyPermission permission = permissions.get(i);
157             printedSomething = permission.dump(pw, packageName, permissionNames,
158                     externalStorageEnforced, printedSomething, dumpState);
159         }
160         if (packageName == null && permissionNames == null) {
161             boolean firstEntry = true;
162             for (final Map.Entry<String, Set<String>> entry : appOpPermissionPackages.entrySet()) {
163                 if (firstEntry) {
164                     firstEntry = false;
165                     if (dumpState.onTitlePrinted()) {
166                         pw.println();
167                     }
168                     pw.println("AppOp Permissions:");
169                 }
170                 pw.print("  AppOp Permission ");
171                 pw.print(entry.getKey());
172                 pw.println(":");
173                 for (final String appOpPackageName : entry.getValue()) {
174                     pw.print("    ");
175                     pw.println(appOpPackageName);
176                 }
177             }
178         }
179     }
180 }
181