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