AppSecurityPermissions.java revision 8aa2e8939c61d788cbc192098465e79f584e173a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2007, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.R; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 2117606f88527eb6c90c51784ae4bc08feda9c77dbRomain Guyimport android.content.res.Resources; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageInfo; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageParser; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PermissionGroupInfo; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PermissionInfo; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager.NameNotFoundException; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.text.Collator; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Comparator; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class contains the SecurityPermissions view implementation. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Initially the package's advanced or dangerous security permissions 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are displayed under categorized 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * groups. Clicking on the additional permissions presents 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * extended information consisting of all groups and permissions. 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To use this view define a LinearLayout or any ViewGroup and add this 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view by instantiating AppSecurityPermissions and invoking getPermissionsView. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class AppSecurityPermissions implements View.OnClickListener { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private enum State { 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NO_PERMS, 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DANGEROUS_ONLY, 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NORMAL_ONLY, 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BOTH 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String TAG = "AppSecurityPermissions"; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean localLOGV = false; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LayoutInflater mInflater; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private PackageManager mPm; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LinearLayout mPermsView; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Map<String, String> mDangerousMap; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Map<String, String> mNormalMap; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<PermissionInfo> mPermsList; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mDefaultGrpLabel; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mDefaultGrpName="DefaultGrp"; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mPermFormat; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mNormalIcon; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mDangerousIcon; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mExpanded; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mShowMaxIcon; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mShowMinIcon; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mShowMore; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private TextView mShowMoreText; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ImageView mShowMoreIcon; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private State mCurrentState; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LinearLayout mNonDangerousList; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LinearLayout mDangerousList; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashMap<String, CharSequence> mGroupLabelCache; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mNoPermsView; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AppSecurityPermissions(Context context, List<PermissionInfo> permList) { 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPm = mContext.getPackageManager(); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermsList = permList; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AppSecurityPermissions(Context context, String packageName) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPm = mContext.getPackageManager(); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermsList = new ArrayList<PermissionInfo>(); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<PermissionInfo> permSet = new HashSet<PermissionInfo>(); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageInfo pkgInfo; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NameNotFoundException e) { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Extract all user permissions 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if((pkgInfo.applicationInfo != null) && (pkgInfo.applicationInfo.uid != -1)) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getAllUsedPermissions(pkgInfo.applicationInfo.uid, permSet); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(PermissionInfo tmpInfo : permSet) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermsList.add(tmpInfo); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AppSecurityPermissions(Context context, PackageParser.Package pkg) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPm = mContext.getPackageManager(); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermsList = new ArrayList<PermissionInfo>(); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<PermissionInfo> permSet = new HashSet<PermissionInfo>(); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(pkg == null) { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 125c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu // Get requested permissions 126c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu if (pkg.requestedPermissions != null) { 127c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu ArrayList<String> strList = pkg.requestedPermissions; 128c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu int size = strList.size(); 129c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu if (size > 0) { 130c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu extractPerms(strList.toArray(new String[size]), permSet); 131c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu } 132c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu } 133c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu // Get permissions related to shared user if any 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(pkg.mSharedUserId != null) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sharedUid; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sharedUid = mPm.getUidForSharedUser(pkg.mSharedUserId); 138c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu getAllUsedPermissions(sharedUid, permSet); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NameNotFoundException e) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Could'nt retrieve shared user id for:"+pkg.packageName); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 143c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu // Retrieve list of permissions 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(PermissionInfo tmpInfo : permSet) { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermsList.add(tmpInfo); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1498aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn /** 1508aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn * Utility to retrieve a view displaying a single permission. 1518aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn */ 1528aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn public static View getPermissionItemView(Context context, 1538aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn CharSequence grpName, CharSequence description, boolean dangerous) { 1548aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn LayoutInflater inflater = (LayoutInflater)context.getSystemService( 1558aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn Context.LAYOUT_INFLATER_SERVICE); 1568aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn Drawable icon = context.getResources().getDrawable(dangerous 1578aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn ? R.drawable.ic_bullet_key_permission : R.drawable.ic_text_dot); 1588aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn return getPermissionItemView(context, inflater, grpName, 1598aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn description, dangerous, icon); 1608aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn } 1618aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void getAllUsedPermissions(int sharedUid, Set<PermissionInfo> permSet) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String sharedPkgList[] = mPm.getPackagesForUid(sharedUid); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(sharedPkgList == null || (sharedPkgList.length == 0)) { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(String sharedPkg : sharedPkgList) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getPermissionsForPackage(sharedPkg, permSet); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void getPermissionsForPackage(String packageName, 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<PermissionInfo> permSet) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageInfo pkgInfo; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NameNotFoundException e) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 181c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu if ((pkgInfo != null) && (pkgInfo.requestedPermissions != null)) { 182c7b14e92075b8a0250ccc8bb4aa21e61d620a708Suchi Amalapurapu extractPerms(pkgInfo.requestedPermissions, permSet); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void extractPerms(String strList[], Set<PermissionInfo> permSet) { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if((strList == null) || (strList.length == 0)) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(String permName:strList) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(tmpPermInfo != null) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permSet.add(tmpPermInfo); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NameNotFoundException e) { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.i(TAG, "Ignoring unknown permission:"+permName); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getPermissionCount() { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPermsList.size(); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View getPermissionsView() { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMore = mPermsView.findViewById(R.id.show_more); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMoreIcon = (ImageView) mShowMore.findViewById(R.id.show_more_icon); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMoreText = (TextView) mShowMore.findViewById(R.id.show_more_text); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDangerousList = (LinearLayout) mPermsView.findViewById(R.id.dangerous_perms_list); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNonDangerousList = (LinearLayout) mPermsView.findViewById(R.id.non_dangerous_perms_list); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNoPermsView = mPermsView.findViewById(R.id.no_permissions); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set up the LinearLayout that acts like a list item. 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMore.setClickable(true); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMore.setOnClickListener(this); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMore.setFocusable(true); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMore.setBackgroundResource(android.R.drawable.list_selector_background); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pick up from framework resources instead. 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultGrpLabel = mContext.getString(R.string.default_permission_group); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPermFormat = mContext.getString(R.string.permissions_format); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMaxIcon = mContext.getResources().getDrawable(R.drawable.expander_ic_maximized); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMinIcon = mContext.getResources().getDrawable(R.drawable.expander_ic_minimized); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set permissions view 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setPermissions(mPermsList); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPermsView; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Canonicalizes the group description before it is displayed to the user. 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO check for internationalization issues remove trailing '.' in str1 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String canonicalizeGroupDesc(String groupDesc) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((groupDesc == null) || (groupDesc.length() == 0)) { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Both str1 and str2 are non-null and are non-zero in size. 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = groupDesc.length(); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(groupDesc.charAt(len-1) == '.') { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project groupDesc = groupDesc.substring(0, len-1); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return groupDesc; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility method that concatenates two strings defined by mPermFormat. 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a null value is returned if both str1 and str2 are null, if one of the strings 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is null the other non null value is returned without formatting 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this is to placate initial error checks 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String formatPermissions(String groupDesc, CharSequence permDesc) { 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(groupDesc == null) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(permDesc == null) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return permDesc.toString(); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project groupDesc = canonicalizeGroupDesc(groupDesc); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(permDesc == null) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return groupDesc; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // groupDesc and permDesc are non null 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return String.format(mPermFormat, groupDesc, permDesc.toString()); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CharSequence getGroupLabel(String grpName) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (grpName == null) { 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //return default label 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultGrpLabel; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence cachedLabel = mGroupLabelCache.get(grpName); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cachedLabel != null) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cachedLabel; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PermissionGroupInfo pgi; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pgi = mPm.getPermissionGroupInfo(grpName, 0); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NameNotFoundException e) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.i(TAG, "Invalid group name:" + grpName); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence label = pgi.loadLabel(mPm).toString(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupLabelCache.put(grpName, label); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return label; 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility method that displays permissions from a map containing group name and 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * list of permission descriptions. 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void displayPermissions(boolean dangerous) { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, String> permInfoMap = dangerous ? mDangerousMap : mNormalMap; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LinearLayout permListView = dangerous ? mDangerousList : mNonDangerousList; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permListView.removeAllViews(); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> permInfoStrSet = permInfoMap.keySet(); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String loopPermGrpInfoStr : permInfoStrSet) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence grpLabel = getGroupLabel(loopPermGrpInfoStr); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //guaranteed that grpLabel wont be null since permissions without groups 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //will belong to the default group 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "Adding view group:" + grpLabel + ", desc:" 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + permInfoMap.get(loopPermGrpInfoStr)); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permListView.addView(getPermissionItemView(grpLabel, 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permInfoMap.get(loopPermGrpInfoStr), dangerous)); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void displayNoPermissions() { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNoPermsView.setVisibility(View.VISIBLE); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3208aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn private View getPermissionItemView(CharSequence grpName, CharSequence permList, 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean dangerous) { 3228aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn return getPermissionItemView(mContext, mInflater, grpName, permList, 3238aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn dangerous, dangerous ? mDangerousIcon : mNormalIcon); 3248aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn } 3258aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn 3268aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn private static View getPermissionItemView(Context context, LayoutInflater inflater, 3278aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) { 3288aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn View permView = inflater.inflate(R.layout.app_permission_item, null); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextView permDescView = (TextView) permView.findViewById(R.id.permission_list); 33217606f88527eb6c90c51784ae4bc08feda9c77dbRomain Guy if (dangerous) { 3338aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn final Resources resources = context.getResources(); 33417606f88527eb6c90c51784ae4bc08feda9c77dbRomain Guy permGrpView.setTextColor(resources.getColor(R.color.perms_dangerous_grp_color)); 33517606f88527eb6c90c51784ae4bc08feda9c77dbRomain Guy permDescView.setTextColor(resources.getColor(R.color.perms_dangerous_perm_color)); 33617606f88527eb6c90c51784ae4bc08feda9c77dbRomain Guy } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project imgView.setImageDrawable(icon); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(grpName != null) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permGrpView.setText(grpName); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permDescView.setText(permList); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permGrpView.setText(permList); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permDescView.setVisibility(View.GONE); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return permView; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void showPermissions() { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch(mCurrentState) { 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NO_PERMS: 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project displayNoPermissions(); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case DANGEROUS_ONLY: 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project displayPermissions(true); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NORMAL_ONLY: 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project displayPermissions(false); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BOTH: 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project displayPermissions(true); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mExpanded) { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project displayPermissions(false); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMoreIcon.setImageDrawable(mShowMaxIcon); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMoreText.setText(R.string.perms_hide); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNonDangerousList.setVisibility(View.VISIBLE); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMoreIcon.setImageDrawable(mShowMinIcon); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMoreText.setText(R.string.perms_show_all); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNonDangerousList.setVisibility(View.GONE); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowMore.setVisibility(View.VISIBLE); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isDisplayablePermission(PermissionInfo pInfo) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(pInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS || 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pInfo.protectionLevel == PermissionInfo.PROTECTION_NORMAL) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility method that aggregates all permission descriptions categorized by group 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Say group1 has perm11, perm12, perm13, the group description will be 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * perm11_Desc, perm12_Desc, perm13_Desc 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void aggregateGroupDescs( 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, List<PermissionInfo> > map, Map<String, String> retMap) { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(map == null) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(retMap == null) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> grpNames = map.keySet(); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<String> grpNamesIter = grpNames.iterator(); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while(grpNamesIter.hasNext()) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String grpDesc = null; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String grpNameKey = grpNamesIter.next(); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project List<PermissionInfo> grpPermsList = map.get(grpNameKey); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(grpPermsList == null) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(PermissionInfo permInfo: grpPermsList) { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence permDesc = permInfo.loadLabel(mPm); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project grpDesc = formatPermissions(grpDesc, permDesc); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Insert grpDesc into map 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(grpDesc != null) { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "Group:"+grpNameKey+" description:"+grpDesc.toString()); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retMap.put(grpNameKey, grpDesc.toString()); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class PermissionInfoComparator implements Comparator<PermissionInfo> { 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private PackageManager mPm; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Collator sCollator = Collator.getInstance(); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PermissionInfoComparator(PackageManager pm) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPm = pm; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int compare(PermissionInfo a, PermissionInfo b) { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence sa = a.loadLabel(mPm); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence sb = b.loadLabel(mPm); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sCollator.compare(sa, sb); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setPermissions(List<PermissionInfo> permList) { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupLabelCache = new HashMap<String, CharSequence>(); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //add the default label so that uncategorized permissions can go here 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupLabelCache.put(mDefaultGrpName, mDefaultGrpLabel); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Map containing group names and a list of permissions under that group 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // categorized as dangerous 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDangerousMap = new HashMap<String, String>(); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Map containing group names and a list of permissions under that group 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // categorized as normal 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNormalMap = new HashMap<String, String>(); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Additional structures needed to ensure that permissions are unique under 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // each group 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, List<PermissionInfo>> dangerousMap = 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashMap<String, List<PermissionInfo>>(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, List<PermissionInfo> > normalMap = 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashMap<String, List<PermissionInfo>>(); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PermissionInfoComparator permComparator = new PermissionInfoComparator(mPm); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (permList != null) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First pass to group permissions 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (PermissionInfo pInfo : permList) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "Processing permission:"+pInfo.name); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(!isDisplayablePermission(pInfo)) { 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable"); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, List<PermissionInfo> > permInfoMap = 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (pInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) ? 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dangerousMap : normalMap; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String grpName = (pInfo.group == null) ? mDefaultGrpName : pInfo.group; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" belongs to group:"+grpName); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project List<PermissionInfo> grpPermsList = permInfoMap.get(grpName); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(grpPermsList == null) { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project grpPermsList = new ArrayList<PermissionInfo>(); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permInfoMap.put(grpName, grpPermsList); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project grpPermsList.add(pInfo); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int idx = Collections.binarySearch(grpPermsList, pInfo, permComparator); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+grpPermsList.size()); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (idx < 0) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project idx = -idx-1; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project grpPermsList.add(idx, pInfo); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Second pass to actually form the descriptions 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look at dangerous permissions first 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project aggregateGroupDescs(dangerousMap, mDangerousMap); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project aggregateGroupDescs(normalMap, mNormalMap); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentState = State.NO_PERMS; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(mDangerousMap.size() > 0) { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentState = (mNormalMap.size() > 0) ? State.BOTH : State.DANGEROUS_ONLY; 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(mNormalMap.size() > 0) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentState = State.NORMAL_ONLY; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "mCurrentState=" + mCurrentState); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project showPermissions(); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(View v) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(localLOGV) Log.i(TAG, "mExpanded="+mExpanded); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mExpanded = !mExpanded; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project showPermissions(); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 506