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.ui; 18 19 import android.app.ActionBar; 20 import android.app.AlertDialog; 21 import android.content.Intent; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageItemInfo; 25 import android.content.pm.PackageManager; 26 import android.content.pm.PackageManager.NameNotFoundException; 27 import android.content.pm.PermissionGroupInfo; 28 import android.content.pm.PermissionInfo; 29 import android.graphics.drawable.Drawable; 30 import android.net.Uri; 31 import android.os.Bundle; 32 import android.provider.Settings; 33 import android.support.v7.preference.Preference; 34 import android.support.v7.preference.Preference.OnPreferenceClickListener; 35 import android.support.v7.preference.PreferenceCategory; 36 import android.support.v7.preference.PreferenceGroup; 37 import android.util.Log; 38 import android.view.MenuItem; 39 40 import com.android.packageinstaller.R; 41 import com.android.packageinstaller.permission.utils.Utils; 42 43 import java.util.ArrayList; 44 import java.util.Collections; 45 import java.util.Comparator; 46 47 public final class AllAppPermissionsFragment extends SettingsWithHeader { 48 49 private static final String LOG_TAG = "AllAppPermissionsFragment"; 50 51 private static final String KEY_OTHER = "other_perms"; 52 newInstance(String packageName)53 public static AllAppPermissionsFragment newInstance(String packageName) { 54 AllAppPermissionsFragment instance = new AllAppPermissionsFragment(); 55 Bundle arguments = new Bundle(); 56 arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); 57 instance.setArguments(arguments); 58 return instance; 59 } 60 61 @Override onCreate(Bundle savedInstanceState)62 public void onCreate(Bundle savedInstanceState) { 63 super.onCreate(savedInstanceState); 64 setHasOptionsMenu(true); 65 final ActionBar ab = getActivity().getActionBar(); 66 if (ab != null) { 67 ab.setTitle(R.string.all_permissions); 68 ab.setDisplayHomeAsUpEnabled(true); 69 } 70 } 71 72 @Override onResume()73 public void onResume() { 74 super.onResume(); 75 updateUi(); 76 } 77 78 @Override onOptionsItemSelected(MenuItem item)79 public boolean onOptionsItemSelected(MenuItem item) { 80 switch (item.getItemId()) { 81 case android.R.id.home: { 82 getFragmentManager().popBackStack(); 83 return true; 84 } 85 } 86 return super.onOptionsItemSelected(item); 87 } 88 updateUi()89 private void updateUi() { 90 if (getPreferenceScreen() != null) { 91 getPreferenceScreen().removeAll(); 92 } 93 addPreferencesFromResource(R.xml.all_permissions); 94 PreferenceGroup otherGroup = (PreferenceGroup) findPreference(KEY_OTHER); 95 ArrayList<Preference> prefs = new ArrayList<>(); // Used for sorting. 96 prefs.add(otherGroup); 97 String pkg = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); 98 otherGroup.removeAll(); 99 PackageManager pm = getContext().getPackageManager(); 100 101 try { 102 PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS); 103 104 ApplicationInfo appInfo = info.applicationInfo; 105 final Drawable icon = appInfo.loadIcon(pm); 106 final CharSequence label = appInfo.loadLabel(pm); 107 Intent infoIntent = null; 108 if (!getActivity().getIntent().getBooleanExtra( 109 AppPermissionsFragment.EXTRA_HIDE_INFO_BUTTON, false)) { 110 infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) 111 .setData(Uri.fromParts("package", pkg, null)); 112 } 113 setHeader(icon, label, infoIntent); 114 115 if (info.requestedPermissions != null) { 116 for (int i = 0; i < info.requestedPermissions.length; i++) { 117 PermissionInfo perm; 118 try { 119 perm = pm.getPermissionInfo(info.requestedPermissions[i], 0); 120 } catch (NameNotFoundException e) { 121 Log.e(LOG_TAG, 122 "Can't get permission info for " + info.requestedPermissions[i], e); 123 continue; 124 } 125 126 if ((perm.flags & PermissionInfo.FLAG_INSTALLED) == 0 127 || (perm.flags & PermissionInfo.FLAG_HIDDEN) != 0) { 128 continue; 129 } 130 131 if (perm.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) { 132 PermissionGroupInfo group = getGroup(perm.group, pm); 133 PreferenceGroup pref = 134 findOrCreate(group != null ? group : perm, pm, prefs); 135 pref.addPreference(getPreference(perm, group, pm)); 136 } else if (perm.protectionLevel == PermissionInfo.PROTECTION_NORMAL) { 137 PermissionGroupInfo group = getGroup(perm.group, pm); 138 otherGroup.addPreference(getPreference(perm, group, pm)); 139 } 140 } 141 } 142 } catch (NameNotFoundException e) { 143 Log.e(LOG_TAG, "Problem getting package info for " + pkg, e); 144 } 145 // Sort an ArrayList of the groups and then set the order from the sorting. 146 Collections.sort(prefs, new Comparator<Preference>() { 147 @Override 148 public int compare(Preference lhs, Preference rhs) { 149 String lKey = lhs.getKey(); 150 String rKey = rhs.getKey(); 151 if (lKey.equals(KEY_OTHER)) { 152 return 1; 153 } else if (rKey.equals(KEY_OTHER)) { 154 return -1; 155 } else if (Utils.isModernPermissionGroup(lKey) 156 != Utils.isModernPermissionGroup(rKey)) { 157 return Utils.isModernPermissionGroup(lKey) ? -1 : 1; 158 } 159 return lhs.getTitle().toString().compareTo(rhs.getTitle().toString()); 160 } 161 }); 162 for (int i = 0; i < prefs.size(); i++) { 163 prefs.get(i).setOrder(i); 164 } 165 } 166 getGroup(String group, PackageManager pm)167 private PermissionGroupInfo getGroup(String group, PackageManager pm) { 168 try { 169 return pm.getPermissionGroupInfo(group, 0); 170 } catch (NameNotFoundException e) { 171 return null; 172 } 173 } 174 findOrCreate(PackageItemInfo group, PackageManager pm, ArrayList<Preference> prefs)175 private PreferenceGroup findOrCreate(PackageItemInfo group, PackageManager pm, 176 ArrayList<Preference> prefs) { 177 PreferenceGroup pref = (PreferenceGroup) findPreference(group.name); 178 if (pref == null) { 179 pref = new PreferenceCategory(getContext()); 180 pref.setKey(group.name); 181 pref.setLayoutResource(R.layout.preference_category_material); 182 pref.setTitle(group.loadLabel(pm)); 183 prefs.add(pref); 184 getPreferenceScreen().addPreference(pref); 185 } 186 return pref; 187 } 188 getPreference(PermissionInfo perm, PermissionGroupInfo group, PackageManager pm)189 private Preference getPreference(PermissionInfo perm, PermissionGroupInfo group, 190 PackageManager pm) { 191 Preference pref = new Preference(getContext()); 192 pref.setLayoutResource(R.layout.preference_permissions); 193 Drawable icon = null; 194 if (perm.icon != 0) { 195 icon = perm.loadIcon(pm); 196 } else if (group != null && group.icon != 0) { 197 icon = group.loadIcon(pm); 198 } else { 199 icon = getContext().getDrawable(R.drawable.ic_perm_device_info); 200 } 201 pref.setIcon(Utils.applyTint(getContext(), icon, android.R.attr.colorControlNormal)); 202 pref.setTitle(perm.loadLabel(pm)); 203 final CharSequence desc = perm.loadDescription(pm); 204 pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { 205 @Override 206 public boolean onPreferenceClick(Preference preference) { 207 new AlertDialog.Builder(getContext()) 208 .setMessage(desc) 209 .setPositiveButton(android.R.string.ok, null) 210 .show(); 211 return true; 212 } 213 }); 214 215 return pref; 216 } 217 }