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