1 /*
2  * Copyright (C) 2015 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.packageinstaller.permission.model;
18 
19 import android.content.Context;
20 import android.content.pm.PackageInfo;
21 import android.content.pm.PackageManager;
22 import android.text.BidiFormatter;
23 
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 
29 public final class AppPermissions {
30     private final ArrayList<AppPermissionGroup> mGroups = new ArrayList<>();
31 
32     private final LinkedHashMap<String, AppPermissionGroup> mNameToGroupMap = new LinkedHashMap<>();
33 
34     private final Context mContext;
35 
36     private final String[] mFilterPermissions;
37 
38     private final CharSequence mAppLabel;
39 
40     private final Runnable mOnErrorCallback;
41 
42     private final boolean mSortGroups;
43 
44     private PackageInfo mPackageInfo;
45 
AppPermissions(Context context, PackageInfo packageInfo, String[] filterPermissions, boolean sortGroups, Runnable onErrorCallback)46     public AppPermissions(Context context, PackageInfo packageInfo, String[] filterPermissions,
47             boolean sortGroups, Runnable onErrorCallback) {
48         mContext = context;
49         mPackageInfo = packageInfo;
50         mFilterPermissions = filterPermissions;
51         mAppLabel = BidiFormatter.getInstance().unicodeWrap(
52                 packageInfo.applicationInfo.loadSafeLabel(
53                 context.getPackageManager()).toString());
54         mSortGroups = sortGroups;
55         mOnErrorCallback = onErrorCallback;
56         loadPermissionGroups();
57     }
58 
getPackageInfo()59     public PackageInfo getPackageInfo() {
60         return mPackageInfo;
61     }
62 
refresh()63     public void refresh() {
64         loadPackageInfo();
65         loadPermissionGroups();
66     }
67 
getAppLabel()68     public CharSequence getAppLabel() {
69         return mAppLabel;
70     }
71 
getPermissionGroup(String name)72     public AppPermissionGroup getPermissionGroup(String name) {
73         return mNameToGroupMap.get(name);
74     }
75 
getPermissionGroups()76     public List<AppPermissionGroup> getPermissionGroups() {
77         return mGroups;
78     }
79 
isReviewRequired()80     public boolean isReviewRequired() {
81         if (!mContext.getPackageManager().isPermissionReviewModeEnabled()) {
82             return false;
83         }
84         final int groupCount = mGroups.size();
85         for (int i = 0; i < groupCount; i++) {
86             AppPermissionGroup group = mGroups.get(i);
87             if (group.isReviewRequired()) {
88                 return true;
89             }
90         }
91         return false;
92     }
93 
loadPackageInfo()94     private void loadPackageInfo() {
95         try {
96             mPackageInfo = mContext.getPackageManager().getPackageInfo(
97                     mPackageInfo.packageName, PackageManager.GET_PERMISSIONS);
98         } catch (PackageManager.NameNotFoundException e) {
99             if (mOnErrorCallback != null) {
100                 mOnErrorCallback.run();
101             }
102         }
103     }
104 
loadPermissionGroups()105     private void loadPermissionGroups() {
106         mGroups.clear();
107 
108         if (mPackageInfo.requestedPermissions == null) {
109             return;
110         }
111 
112         if (mFilterPermissions != null) {
113             for (String filterPermission : mFilterPermissions) {
114                 for (String requestedPerm : mPackageInfo.requestedPermissions) {
115                     if (!filterPermission.equals(requestedPerm)) {
116                         continue;
117                     }
118                     addPermissionGroupIfNeeded(requestedPerm);
119                     break;
120                 }
121             }
122         } else {
123             for (String requestedPerm : mPackageInfo.requestedPermissions) {
124                 addPermissionGroupIfNeeded(requestedPerm);
125             }
126         }
127 
128         if (mSortGroups) {
129             Collections.sort(mGroups);
130         }
131 
132         mNameToGroupMap.clear();
133         for (AppPermissionGroup group : mGroups) {
134             mNameToGroupMap.put(group.getName(), group);
135         }
136     }
137 
addPermissionGroupIfNeeded(String permission)138     private void addPermissionGroupIfNeeded(String permission) {
139         if (hasGroupForPermission(permission)) {
140             return;
141         }
142 
143         AppPermissionGroup group = AppPermissionGroup.create(mContext,
144                 mPackageInfo, permission);
145         if (group == null) {
146             return;
147         }
148 
149         mGroups.add(group);
150     }
151 
hasGroupForPermission(String permission)152     private boolean hasGroupForPermission(String permission) {
153         for (AppPermissionGroup group : mGroups) {
154             if (group.hasPermission(permission)) {
155                 return true;
156             }
157         }
158         return false;
159     }
160 }
161