AppPermissions.java revision 03dc824d37099b29acb5a0aa28e881d5b05cce0e
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
17package com.android.packageinstaller.permission.model;
18
19import android.content.Context;
20import android.content.pm.PackageInfo;
21import android.content.pm.PackageManager;
22import android.text.BidiFormatter;
23import android.text.TextPaint;
24import android.text.TextUtils;
25
26import com.android.packageinstaller.DeviceUtils;
27
28import java.util.ArrayList;
29import java.util.Collections;
30import java.util.LinkedHashMap;
31import java.util.List;
32
33public final class AppPermissions {
34    private static final float MAX_APP_LABEL_LENGTH_PIXELS = 500;
35
36    private static final TextPaint sAppLabelEllipsizePaint = new TextPaint();
37    static {
38        sAppLabelEllipsizePaint.setAntiAlias(true);
39        // Both text size and width are given in absolute pixels, for consistent truncation
40        // across devices; this value corresponds to the default 14dip size on an xdhpi device.
41        sAppLabelEllipsizePaint.setTextSize(42);
42    }
43
44    private final ArrayList<AppPermissionGroup> mGroups = new ArrayList<>();
45
46    private final LinkedHashMap<String, AppPermissionGroup> mNameToGroupMap = new LinkedHashMap<>();
47
48    private final Context mContext;
49
50    private final String[] mFilterPermissions;
51
52    private final CharSequence mAppLabel;
53
54    private final Runnable mOnErrorCallback;
55
56    private final boolean mSortGroups;
57
58    private PackageInfo mPackageInfo;
59
60    public AppPermissions(Context context, PackageInfo packageInfo, String[] permissions,
61            boolean sortGroups, Runnable onErrorCallback) {
62        mContext = context;
63        mPackageInfo = packageInfo;
64        mFilterPermissions = permissions;
65        mAppLabel = loadEllipsizedAppLabel(context, packageInfo);
66        mSortGroups = sortGroups;
67        mOnErrorCallback = onErrorCallback;
68        loadPermissionGroups();
69    }
70
71    public PackageInfo getPackageInfo() {
72        return mPackageInfo;
73    }
74
75    public void refresh() {
76        loadPackageInfo();
77        loadPermissionGroups();
78    }
79
80    public CharSequence getAppLabel() {
81        return mAppLabel;
82    }
83
84    public AppPermissionGroup getPermissionGroup(String name) {
85        return mNameToGroupMap.get(name);
86    }
87
88    public List<AppPermissionGroup> getPermissionGroups() {
89        return mGroups;
90    }
91
92
93    private void loadPackageInfo() {
94        try {
95            mPackageInfo = mContext.getPackageManager().getPackageInfo(
96                    mPackageInfo.packageName, PackageManager.GET_PERMISSIONS);
97        } catch (PackageManager.NameNotFoundException e) {
98            if (mOnErrorCallback != null) {
99                mOnErrorCallback.run();
100            }
101        }
102    }
103
104    private void loadPermissionGroups() {
105        mGroups.clear();
106
107        if (mPackageInfo.requestedPermissions == null) {
108            return;
109        }
110
111        if (mFilterPermissions != null) {
112            for (String filterPermission : mFilterPermissions) {
113                for (String requestedPerm : mPackageInfo.requestedPermissions) {
114                    if (!filterPermission.equals(requestedPerm)) {
115                        continue;
116                    }
117
118                    if (hasGroupForPermission(requestedPerm)) {
119                        break;
120                    }
121
122                    AppPermissionGroup group = AppPermissionGroup.create(mContext,
123                            mPackageInfo, requestedPerm);
124                    if (group == null) {
125                        break;
126                    }
127
128                    mGroups.add(group);
129                    break;
130                }
131            }
132        } else {
133            for (String requestedPerm : mPackageInfo.requestedPermissions) {
134                if (hasGroupForPermission(requestedPerm)) {
135                    continue;
136                }
137
138                AppPermissionGroup group = AppPermissionGroup.create(mContext,
139                        mPackageInfo, requestedPerm);
140                if (group == null) {
141                    continue;
142                }
143
144                mGroups.add(group);
145            }
146        }
147
148        if (mSortGroups) {
149            Collections.sort(mGroups);
150        }
151
152        mNameToGroupMap.clear();
153        for (AppPermissionGroup group : mGroups) {
154            mNameToGroupMap.put(group.getName(), group);
155        }
156    }
157
158    private boolean hasGroupForPermission(String permission) {
159        for (AppPermissionGroup group : mGroups) {
160            if (group.hasPermission(permission)) {
161                return true;
162            }
163        }
164        return false;
165    }
166
167    private static CharSequence loadEllipsizedAppLabel(Context context, PackageInfo packageInfo) {
168        String label = packageInfo.applicationInfo.loadLabel(
169                context.getPackageManager()).toString();
170        String ellipsizedLabel = label.replace("\n", " ");
171        if (!DeviceUtils.isWear(context)) {
172            // Only ellipsize for non-Wear devices.
173            ellipsizedLabel = TextUtils.ellipsize(ellipsizedLabel, sAppLabelEllipsizePaint,
174                MAX_APP_LABEL_LENGTH_PIXELS, TextUtils.TruncateAt.END).toString();
175        }
176        return BidiFormatter.getInstance().unicodeWrap(ellipsizedLabel);
177    }
178}
179