1/*
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17package android.widget;
18
19import com.android.internal.R;
20
21import android.app.AlertDialog;
22import android.content.Context;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.PackageInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.PackageManager.NameNotFoundException;
27import android.content.pm.PermissionGroupInfo;
28import android.content.pm.PermissionInfo;
29import android.graphics.drawable.Drawable;
30import android.os.Parcel;
31import android.text.SpannableStringBuilder;
32import android.text.TextUtils;
33import android.util.AttributeSet;
34import android.util.Log;
35import android.view.LayoutInflater;
36import android.view.View;
37import android.view.ViewGroup;
38
39import java.text.Collator;
40import java.util.ArrayList;
41import java.util.Collections;
42import java.util.Comparator;
43import java.util.HashMap;
44import java.util.HashSet;
45import java.util.List;
46import java.util.Map;
47import java.util.Set;
48
49/**
50 * This class contains the SecurityPermissions view implementation.
51 * Initially the package's advanced or dangerous security permissions
52 * are displayed under categorized
53 * groups. Clicking on the additional permissions presents
54 * extended information consisting of all groups and permissions.
55 * To use this view define a LinearLayout or any ViewGroup and add this
56 * view by instantiating AppSecurityPermissions and invoking getPermissionsView.
57 *
58 * {@hide}
59 */
60public class AppSecurityPermissions {
61
62    public static final int WHICH_PERSONAL = 1<<0;
63    public static final int WHICH_DEVICE = 1<<1;
64    public static final int WHICH_NEW = 1<<2;
65    public static final int WHICH_ALL = 0xffff;
66
67    private final static String TAG = "AppSecurityPermissions";
68    private final static boolean localLOGV = false;
69    private Context mContext;
70    private LayoutInflater mInflater;
71    private PackageManager mPm;
72    private PackageInfo mInstalledPackageInfo;
73    private final Map<String, MyPermissionGroupInfo> mPermGroups
74            = new HashMap<String, MyPermissionGroupInfo>();
75    private final List<MyPermissionGroupInfo> mPermGroupsList
76            = new ArrayList<MyPermissionGroupInfo>();
77    private final PermissionGroupInfoComparator mPermGroupComparator;
78    private final PermissionInfoComparator mPermComparator;
79    private List<MyPermissionInfo> mPermsList;
80    private CharSequence mNewPermPrefix;
81    private Drawable mNormalIcon;
82    private Drawable mDangerousIcon;
83
84    static class MyPermissionGroupInfo extends PermissionGroupInfo {
85        CharSequence mLabel;
86
87        final ArrayList<MyPermissionInfo> mNewPermissions = new ArrayList<MyPermissionInfo>();
88        final ArrayList<MyPermissionInfo> mPersonalPermissions = new ArrayList<MyPermissionInfo>();
89        final ArrayList<MyPermissionInfo> mDevicePermissions = new ArrayList<MyPermissionInfo>();
90        final ArrayList<MyPermissionInfo> mAllPermissions = new ArrayList<MyPermissionInfo>();
91
92        MyPermissionGroupInfo(PermissionInfo perm) {
93            name = perm.packageName;
94            packageName = perm.packageName;
95        }
96
97        MyPermissionGroupInfo(PermissionGroupInfo info) {
98            super(info);
99        }
100
101        public Drawable loadGroupIcon(PackageManager pm) {
102            if (icon != 0) {
103                return loadIcon(pm);
104            } else {
105                ApplicationInfo appInfo;
106                try {
107                    appInfo = pm.getApplicationInfo(packageName, 0);
108                    return appInfo.loadIcon(pm);
109                } catch (NameNotFoundException e) {
110                }
111            }
112            return null;
113        }
114    }
115
116    static class MyPermissionInfo extends PermissionInfo {
117        CharSequence mLabel;
118
119        /**
120         * PackageInfo.requestedPermissionsFlags for the new package being installed.
121         */
122        int mNewReqFlags;
123
124        /**
125         * PackageInfo.requestedPermissionsFlags for the currently installed
126         * package, if it is installed.
127         */
128        int mExistingReqFlags;
129
130        /**
131         * True if this should be considered a new permission.
132         */
133        boolean mNew;
134
135        MyPermissionInfo() {
136        }
137
138        MyPermissionInfo(PermissionInfo info) {
139            super(info);
140        }
141
142        MyPermissionInfo(MyPermissionInfo info) {
143            super(info);
144            mNewReqFlags = info.mNewReqFlags;
145            mExistingReqFlags = info.mExistingReqFlags;
146            mNew = info.mNew;
147        }
148    }
149
150    public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
151        MyPermissionGroupInfo mGroup;
152        MyPermissionInfo mPerm;
153        AlertDialog mDialog;
154
155        public PermissionItemView(Context context, AttributeSet attrs) {
156            super(context, attrs);
157            setClickable(true);
158        }
159
160        public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
161                boolean first, CharSequence newPermPrefix) {
162            mGroup = grp;
163            mPerm = perm;
164
165            ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
166            TextView permNameView = (TextView) findViewById(R.id.perm_name);
167
168            PackageManager pm = getContext().getPackageManager();
169            Drawable icon = null;
170            if (first) {
171                icon = grp.loadGroupIcon(pm);
172            }
173            CharSequence label = perm.mLabel;
174            if (perm.mNew && newPermPrefix != null) {
175                // If this is a new permission, format it appropriately.
176                SpannableStringBuilder builder = new SpannableStringBuilder();
177                Parcel parcel = Parcel.obtain();
178                TextUtils.writeToParcel(newPermPrefix, parcel, 0);
179                parcel.setDataPosition(0);
180                CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
181                parcel.recycle();
182                builder.append(newStr);
183                builder.append(label);
184                label = builder;
185            }
186
187            permGrpIcon.setImageDrawable(icon);
188            permNameView.setText(label);
189            setOnClickListener(this);
190            if (localLOGV) Log.i(TAG, "Made perm item " + perm.name
191                    + ": " + label + " in group " + grp.name);
192        }
193
194        @Override
195        public void onClick(View v) {
196            if (mGroup != null && mPerm != null) {
197                if (mDialog != null) {
198                    mDialog.dismiss();
199                }
200                PackageManager pm = getContext().getPackageManager();
201                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
202                builder.setTitle(mGroup.mLabel);
203                if (mPerm.descriptionRes != 0) {
204                    builder.setMessage(mPerm.loadDescription(pm));
205                } else {
206                    CharSequence appName;
207                    try {
208                        ApplicationInfo app = pm.getApplicationInfo(mPerm.packageName, 0);
209                        appName = app.loadLabel(pm);
210                    } catch (NameNotFoundException e) {
211                        appName = mPerm.packageName;
212                    }
213                    StringBuilder sbuilder = new StringBuilder(128);
214                    sbuilder.append(getContext().getString(
215                            R.string.perms_description_app, appName));
216                    sbuilder.append("\n\n");
217                    sbuilder.append(mPerm.name);
218                    builder.setMessage(sbuilder.toString());
219                }
220                builder.setCancelable(true);
221                builder.setIcon(mGroup.loadGroupIcon(pm));
222                mDialog = builder.show();
223                mDialog.setCanceledOnTouchOutside(true);
224            }
225        }
226
227        @Override
228        protected void onDetachedFromWindow() {
229            super.onDetachedFromWindow();
230            if (mDialog != null) {
231                mDialog.dismiss();
232            }
233        }
234    }
235
236    public AppSecurityPermissions(Context context, List<PermissionInfo> permList) {
237        mContext = context;
238        mPm = mContext.getPackageManager();
239        loadResources();
240        mPermComparator = new PermissionInfoComparator();
241        mPermGroupComparator = new PermissionGroupInfoComparator();
242        for (PermissionInfo pi : permList) {
243            mPermsList.add(new MyPermissionInfo(pi));
244        }
245        setPermissions(mPermsList);
246    }
247
248    public AppSecurityPermissions(Context context, String packageName) {
249        mContext = context;
250        mPm = mContext.getPackageManager();
251        loadResources();
252        mPermComparator = new PermissionInfoComparator();
253        mPermGroupComparator = new PermissionGroupInfoComparator();
254        mPermsList = new ArrayList<MyPermissionInfo>();
255        Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
256        PackageInfo pkgInfo;
257        try {
258            pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
259        } catch (NameNotFoundException e) {
260            Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
261            return;
262        }
263        // Extract all user permissions
264        if((pkgInfo.applicationInfo != null) && (pkgInfo.applicationInfo.uid != -1)) {
265            getAllUsedPermissions(pkgInfo.applicationInfo.uid, permSet);
266        }
267        for(MyPermissionInfo tmpInfo : permSet) {
268            mPermsList.add(tmpInfo);
269        }
270        setPermissions(mPermsList);
271    }
272
273    public AppSecurityPermissions(Context context, PackageInfo info) {
274        mContext = context;
275        mPm = mContext.getPackageManager();
276        loadResources();
277        mPermComparator = new PermissionInfoComparator();
278        mPermGroupComparator = new PermissionGroupInfoComparator();
279        mPermsList = new ArrayList<MyPermissionInfo>();
280        Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
281        if(info == null) {
282            return;
283        }
284
285        // Convert to a PackageInfo
286        PackageInfo installedPkgInfo = null;
287        // Get requested permissions
288        if (info.requestedPermissions != null) {
289            try {
290                installedPkgInfo = mPm.getPackageInfo(info.packageName,
291                        PackageManager.GET_PERMISSIONS);
292            } catch (NameNotFoundException e) {
293            }
294            extractPerms(info, permSet, installedPkgInfo);
295        }
296        // Get permissions related to  shared user if any
297        if (info.sharedUserId != null) {
298            int sharedUid;
299            try {
300                sharedUid = mPm.getUidForSharedUser(info.sharedUserId);
301                getAllUsedPermissions(sharedUid, permSet);
302            } catch (NameNotFoundException e) {
303                Log.w(TAG, "Could'nt retrieve shared user id for:"+info.packageName);
304            }
305        }
306        // Retrieve list of permissions
307        for (MyPermissionInfo tmpInfo : permSet) {
308            mPermsList.add(tmpInfo);
309        }
310        setPermissions(mPermsList);
311    }
312
313    private void loadResources() {
314        // Pick up from framework resources instead.
315        mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
316        mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
317        mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
318    }
319
320    /**
321     * Utility to retrieve a view displaying a single permission.  This provides
322     * the old UI layout for permissions; it is only here for the device admin
323     * settings to continue to use.
324     */
325    public static View getPermissionItemView(Context context,
326            CharSequence grpName, CharSequence description, boolean dangerous) {
327        LayoutInflater inflater = (LayoutInflater)context.getSystemService(
328                Context.LAYOUT_INFLATER_SERVICE);
329        Drawable icon = context.getResources().getDrawable(dangerous
330                ? R.drawable.ic_bullet_key_permission : R.drawable.ic_text_dot);
331        return getPermissionItemViewOld(context, inflater, grpName,
332                description, dangerous, icon);
333    }
334
335    public PackageInfo getInstalledPackageInfo() {
336        return mInstalledPackageInfo;
337    }
338
339    private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
340        String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
341        if(sharedPkgList == null || (sharedPkgList.length == 0)) {
342            return;
343        }
344        for(String sharedPkg : sharedPkgList) {
345            getPermissionsForPackage(sharedPkg, permSet);
346        }
347    }
348
349    private void getPermissionsForPackage(String packageName,
350            Set<MyPermissionInfo> permSet) {
351        PackageInfo pkgInfo;
352        try {
353            pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
354        } catch (NameNotFoundException e) {
355            Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
356            return;
357        }
358        if ((pkgInfo != null) && (pkgInfo.requestedPermissions != null)) {
359            extractPerms(pkgInfo, permSet, pkgInfo);
360        }
361    }
362
363    private void extractPerms(PackageInfo info, Set<MyPermissionInfo> permSet,
364            PackageInfo installedPkgInfo) {
365        String[] strList = info.requestedPermissions;
366        int[] flagsList = info.requestedPermissionsFlags;
367        if ((strList == null) || (strList.length == 0)) {
368            return;
369        }
370        mInstalledPackageInfo = installedPkgInfo;
371        for (int i=0; i<strList.length; i++) {
372            String permName = strList[i];
373            // If we are only looking at an existing app, then we only
374            // care about permissions that have actually been granted to it.
375            if (installedPkgInfo != null && info == installedPkgInfo) {
376                if ((flagsList[i]&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) {
377                    continue;
378                }
379            }
380            try {
381                PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0);
382                if (tmpPermInfo == null) {
383                    continue;
384                }
385                int existingIndex = -1;
386                if (installedPkgInfo != null
387                        && installedPkgInfo.requestedPermissions != null) {
388                    for (int j=0; j<installedPkgInfo.requestedPermissions.length; j++) {
389                        if (permName.equals(installedPkgInfo.requestedPermissions[j])) {
390                            existingIndex = j;
391                            break;
392                        }
393                    }
394                }
395                final int existingFlags = existingIndex >= 0 ?
396                        installedPkgInfo.requestedPermissionsFlags[existingIndex] : 0;
397                if (!isDisplayablePermission(tmpPermInfo, flagsList[i], existingFlags)) {
398                    // This is not a permission that is interesting for the user
399                    // to see, so skip it.
400                    continue;
401                }
402                final String origGroupName = tmpPermInfo.group;
403                String groupName = origGroupName;
404                if (groupName == null) {
405                    groupName = tmpPermInfo.packageName;
406                    tmpPermInfo.group = groupName;
407                }
408                MyPermissionGroupInfo group = mPermGroups.get(groupName);
409                if (group == null) {
410                    PermissionGroupInfo grp = null;
411                    if (origGroupName != null) {
412                        grp = mPm.getPermissionGroupInfo(origGroupName, 0);
413                    }
414                    if (grp != null) {
415                        group = new MyPermissionGroupInfo(grp);
416                    } else {
417                        // We could be here either because the permission
418                        // didn't originally specify a group or the group it
419                        // gave couldn't be found.  In either case, we consider
420                        // its group to be the permission's package name.
421                        tmpPermInfo.group = tmpPermInfo.packageName;
422                        group = mPermGroups.get(tmpPermInfo.group);
423                        if (group == null) {
424                            group = new MyPermissionGroupInfo(tmpPermInfo);
425                        }
426                        group = new MyPermissionGroupInfo(tmpPermInfo);
427                    }
428                    mPermGroups.put(tmpPermInfo.group, group);
429                }
430                final boolean newPerm = installedPkgInfo != null
431                        && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
432                MyPermissionInfo myPerm = new MyPermissionInfo(tmpPermInfo);
433                myPerm.mNewReqFlags = flagsList[i];
434                myPerm.mExistingReqFlags = existingFlags;
435                // This is a new permission if the app is already installed and
436                // doesn't currently hold this permission.
437                myPerm.mNew = newPerm;
438                permSet.add(myPerm);
439            } catch (NameNotFoundException e) {
440                Log.i(TAG, "Ignoring unknown permission:"+permName);
441            }
442        }
443    }
444
445    public int getPermissionCount() {
446        return getPermissionCount(WHICH_ALL);
447    }
448
449    private List<MyPermissionInfo> getPermissionList(MyPermissionGroupInfo grp, int which) {
450        if (which == WHICH_NEW) {
451            return grp.mNewPermissions;
452        } else if (which == WHICH_PERSONAL) {
453            return grp.mPersonalPermissions;
454        } else if (which == WHICH_DEVICE) {
455            return grp.mDevicePermissions;
456        } else {
457            return grp.mAllPermissions;
458        }
459    }
460
461    public int getPermissionCount(int which) {
462        int N = 0;
463        for (int i=0; i<mPermGroupsList.size(); i++) {
464            N += getPermissionList(mPermGroupsList.get(i), which).size();
465        }
466        return N;
467    }
468
469    public View getPermissionsView() {
470        return getPermissionsView(WHICH_ALL);
471    }
472
473    public View getPermissionsView(int which) {
474        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
475
476        LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
477        LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
478        View noPermsView = permsView.findViewById(R.id.no_permissions);
479
480        displayPermissions(mPermGroupsList, displayList, which);
481        if (displayList.getChildCount() <= 0) {
482            noPermsView.setVisibility(View.VISIBLE);
483        }
484
485        return permsView;
486    }
487
488    /**
489     * Utility method that displays permissions from a map containing group name and
490     * list of permission descriptions.
491     */
492    private void displayPermissions(List<MyPermissionGroupInfo> groups,
493            LinearLayout permListView, int which) {
494        permListView.removeAllViews();
495
496        int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
497
498        for (int i=0; i<groups.size(); i++) {
499            MyPermissionGroupInfo grp = groups.get(i);
500            final List<MyPermissionInfo> perms = getPermissionList(grp, which);
501            for (int j=0; j<perms.size(); j++) {
502                MyPermissionInfo perm = perms.get(j);
503                View view = getPermissionItemView(grp, perm, j == 0,
504                        which != WHICH_NEW ? mNewPermPrefix : null);
505                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
506                        ViewGroup.LayoutParams.MATCH_PARENT,
507                        ViewGroup.LayoutParams.WRAP_CONTENT);
508                if (j == 0) {
509                    lp.topMargin = spacing;
510                }
511                if (j == grp.mAllPermissions.size()-1) {
512                    lp.bottomMargin = spacing;
513                }
514                if (permListView.getChildCount() == 0) {
515                    lp.topMargin *= 2;
516                }
517                permListView.addView(view, lp);
518            }
519        }
520    }
521
522    private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
523            MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) {
524        return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix);
525    }
526
527    private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
528            MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
529            CharSequence newPermPrefix) {
530        PermissionItemView permView = (PermissionItemView)inflater.inflate(
531                (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0
532                        ? R.layout.app_permission_item_money : R.layout.app_permission_item,
533                null);
534        permView.setPermission(grp, perm, first, newPermPrefix);
535        return permView;
536    }
537
538    private static View getPermissionItemViewOld(Context context, LayoutInflater inflater,
539            CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
540        View permView = inflater.inflate(R.layout.app_permission_item_old, null);
541
542        TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
543        TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
544
545        ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
546        imgView.setImageDrawable(icon);
547        if(grpName != null) {
548            permGrpView.setText(grpName);
549            permDescView.setText(permList);
550        } else {
551            permGrpView.setText(permList);
552            permDescView.setVisibility(View.GONE);
553        }
554        return permView;
555    }
556
557    private boolean isDisplayablePermission(PermissionInfo pInfo, int newReqFlags,
558            int existingReqFlags) {
559        final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
560        // Dangerous and normal permissions are always shown to the user.
561        if (base == PermissionInfo.PROTECTION_DANGEROUS ||
562                base == PermissionInfo.PROTECTION_NORMAL) {
563            return true;
564        }
565        // Development permissions are only shown to the user if they are already
566        // granted to the app -- if we are installing an app and they are not
567        // already granted, they will not be granted as part of the install.
568        if ((existingReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
569                && (pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
570            if (localLOGV) Log.i(TAG, "Special perm " + pInfo.name
571                    + ": protlevel=0x" + Integer.toHexString(pInfo.protectionLevel));
572            return true;
573        }
574        return false;
575    }
576
577    private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
578        private final Collator sCollator = Collator.getInstance();
579        PermissionGroupInfoComparator() {
580        }
581        public final int compare(MyPermissionGroupInfo a, MyPermissionGroupInfo b) {
582            if (((a.flags^b.flags)&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
583                return ((a.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) ? -1 : 1;
584            }
585            if (a.priority != b.priority) {
586                return a.priority > b.priority ? -1 : 1;
587            }
588            return sCollator.compare(a.mLabel, b.mLabel);
589        }
590    }
591
592    private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
593        private final Collator sCollator = Collator.getInstance();
594        PermissionInfoComparator() {
595        }
596        public final int compare(MyPermissionInfo a, MyPermissionInfo b) {
597            return sCollator.compare(a.mLabel, b.mLabel);
598        }
599    }
600
601    private void addPermToList(List<MyPermissionInfo> permList,
602            MyPermissionInfo pInfo) {
603        if (pInfo.mLabel == null) {
604            pInfo.mLabel = pInfo.loadLabel(mPm);
605        }
606        int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
607        if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
608        if (idx < 0) {
609            idx = -idx-1;
610            permList.add(idx, pInfo);
611        }
612    }
613
614    private void setPermissions(List<MyPermissionInfo> permList) {
615        if (permList != null) {
616            // First pass to group permissions
617            for (MyPermissionInfo pInfo : permList) {
618                if(localLOGV) Log.i(TAG, "Processing permission:"+pInfo.name);
619                if(!isDisplayablePermission(pInfo, pInfo.mNewReqFlags, pInfo.mExistingReqFlags)) {
620                    if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
621                    continue;
622                }
623                MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
624                if (group != null) {
625                    pInfo.mLabel = pInfo.loadLabel(mPm);
626                    addPermToList(group.mAllPermissions, pInfo);
627                    if (pInfo.mNew) {
628                        addPermToList(group.mNewPermissions, pInfo);
629                    }
630                    if ((group.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
631                        addPermToList(group.mPersonalPermissions, pInfo);
632                    } else {
633                        addPermToList(group.mDevicePermissions, pInfo);
634                    }
635                }
636            }
637        }
638
639        for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
640            if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
641                pgrp.mLabel = pgrp.loadLabel(mPm);
642            } else {
643                ApplicationInfo app;
644                try {
645                    app = mPm.getApplicationInfo(pgrp.packageName, 0);
646                    pgrp.mLabel = app.loadLabel(mPm);
647                } catch (NameNotFoundException e) {
648                    pgrp.mLabel = pgrp.loadLabel(mPm);
649                }
650            }
651            mPermGroupsList.add(pgrp);
652        }
653        Collections.sort(mPermGroupsList, mPermGroupComparator);
654        if (localLOGV) {
655            for (MyPermissionGroupInfo grp : mPermGroupsList) {
656                Log.i(TAG, "Group " + grp.name + " personal="
657                        + ((grp.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0)
658                        + " priority=" + grp.priority);
659            }
660        }
661    }
662}
663