• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.television;
18 
19 import android.Manifest;
20 import android.app.ActionBar;
21 import android.app.AlertDialog;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.PackageInfo;
26 import android.content.pm.PackageItemInfo;
27 import android.content.pm.PackageManager;
28 import android.content.pm.PackageManager.NameNotFoundException;
29 import android.content.pm.PermissionGroupInfo;
30 import android.content.pm.PermissionInfo;
31 import android.graphics.drawable.Drawable;
32 import android.net.Uri;
33 import android.os.Build;
34 import android.os.Bundle;
35 import android.provider.Settings;
36 import android.support.v14.preference.SwitchPreference;
37 import android.support.v7.preference.Preference;
38 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
39 import android.support.v7.preference.Preference.OnPreferenceClickListener;
40 import android.support.v7.preference.PreferenceCategory;
41 import android.support.v7.preference.PreferenceGroup;
42 import android.util.Log;
43 import android.view.MenuItem;
44 
45 import com.android.packageinstaller.R;
46 import com.android.packageinstaller.permission.model.AppPermissionGroup;
47 import com.android.packageinstaller.permission.model.AppPermissions;
48 import com.android.packageinstaller.permission.utils.Utils;
49 
50 import java.util.ArrayList;
51 import java.util.Collections;
52 import java.util.Comparator;
53 
54 public final class AllAppPermissionsFragment extends SettingsWithHeader {
55 
56     private static final String LOG_TAG = "AllAppPermissionsFragment";
57 
58     private static final String KEY_OTHER = "other_perms";
59 
60     private PackageInfo mPackageInfo;
61 
62     private AppPermissions mAppPermissions;
63 
newInstance(String packageName)64     public static AllAppPermissionsFragment newInstance(String packageName) {
65         AllAppPermissionsFragment instance = new AllAppPermissionsFragment();
66         Bundle arguments = new Bundle();
67         arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
68         instance.setArguments(arguments);
69         return instance;
70     }
71 
72     @Override
onCreate(Bundle savedInstanceState)73     public void onCreate(Bundle savedInstanceState) {
74         super.onCreate(savedInstanceState);
75         setHasOptionsMenu(true);
76         final ActionBar ab = getActivity().getActionBar();
77         if (ab != null) {
78             ab.setTitle(R.string.all_permissions);
79             ab.setDisplayHomeAsUpEnabled(true);
80         }
81 
82         String pkg = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
83         try {
84             mPackageInfo = getActivity().getPackageManager().getPackageInfo(pkg,
85                     PackageManager.GET_PERMISSIONS);
86         } catch (NameNotFoundException e) {
87             getActivity().finish();
88         }
89 
90         mAppPermissions = new AppPermissions(getActivity(), mPackageInfo, null, false,
91                 new Runnable() {
92             @Override
93             public void run() {
94                 getActivity().finish();
95             }
96         });
97     }
98 
99     @Override
onResume()100     public void onResume() {
101         super.onResume();
102         updateUi();
103     }
104 
105     @Override
onOptionsItemSelected(MenuItem item)106     public boolean onOptionsItemSelected(MenuItem item) {
107         switch (item.getItemId()) {
108             case android.R.id.home: {
109                 getFragmentManager().popBackStack();
110                 return true;
111             }
112         }
113         return super.onOptionsItemSelected(item);
114     }
115 
getOtherGroup()116     private PreferenceGroup getOtherGroup() {
117         PreferenceGroup otherGroup = (PreferenceGroup) findPreference(KEY_OTHER);
118         if (otherGroup == null) {
119             otherGroup = new PreferenceCategory(getPreferenceManager().getContext());
120             otherGroup.setKey(KEY_OTHER);
121             otherGroup.setTitle(getString(R.string.other_permissions));
122             getPreferenceScreen().addPreference(otherGroup);
123         }
124         return otherGroup;
125     }
126 
updateUi()127     private void updateUi() {
128         getPreferenceScreen().removeAll();
129 
130         ArrayList<Preference> prefs = new ArrayList<>(); // Used for sorting.
131         PackageManager pm = getActivity().getPackageManager();
132 
133         ApplicationInfo appInfo = mPackageInfo.applicationInfo;
134         final Drawable icon = appInfo.loadIcon(pm);
135         final CharSequence label = appInfo.loadLabel(pm);
136         Intent infoIntent = null;
137         if (!getActivity().getIntent().getBooleanExtra(
138                 AppPermissionsFragment.EXTRA_HIDE_INFO_BUTTON, false)) {
139             infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
140                     .setData(Uri.fromParts("package", mPackageInfo.packageName, null));
141         }
142         setHeader(icon, label, infoIntent, null);
143 
144         if (mPackageInfo.requestedPermissions != null) {
145             for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) {
146                 PermissionInfo perm;
147                 try {
148                     perm = pm.getPermissionInfo(mPackageInfo.requestedPermissions[i], 0);
149                 } catch (NameNotFoundException e) {
150                     Log.e(LOG_TAG, "Can't get permission info for "
151                             + mPackageInfo.requestedPermissions[i], e);
152                     continue;
153                 }
154 
155                 if ((perm.flags & PermissionInfo.FLAG_INSTALLED) == 0
156                         || (perm.flags & PermissionInfo.FLAG_REMOVED) != 0) {
157                     continue;
158                 }
159 
160                 PermissionGroupInfo group = getGroup(perm.group, pm);
161                 if (perm.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
162                     PreferenceGroup pref = findOrCreate(group != null ? group : perm, pm, prefs);
163                     pref.addPreference(getPreference(perm, group));
164                 } else if (perm.protectionLevel == PermissionInfo.PROTECTION_NORMAL) {
165                     PreferenceGroup otherGroup = getOtherGroup();
166                     if (prefs.indexOf(otherGroup) < 0) {
167                         prefs.add(otherGroup);
168                     }
169                     getOtherGroup().addPreference(getPreference(perm, group));
170                 }
171             }
172         }
173 
174         // Sort an ArrayList of the groups and then set the order from the sorting.
175         Collections.sort(prefs, new Comparator<Preference>() {
176             @Override
177             public int compare(Preference lhs, Preference rhs) {
178                 String lKey = lhs.getKey();
179                 String rKey = rhs.getKey();
180                 if (lKey.equals(KEY_OTHER)) {
181                     return 1;
182                 } else if (rKey.equals(KEY_OTHER)) {
183                     return -1;
184                 } else if (Utils.isModernPermissionGroup(lKey)
185                         != Utils.isModernPermissionGroup(rKey)) {
186                     return Utils.isModernPermissionGroup(lKey) ? -1 : 1;
187                 }
188                 return lhs.getTitle().toString().compareTo(rhs.getTitle().toString());
189             }
190         });
191         for (int i = 0; i < prefs.size(); i++) {
192             prefs.get(i).setOrder(i);
193         }
194     }
195 
getGroup(String group, PackageManager pm)196     private PermissionGroupInfo getGroup(String group, PackageManager pm) {
197         try {
198             return pm.getPermissionGroupInfo(group, 0);
199         } catch (NameNotFoundException e) {
200             return null;
201         }
202     }
203 
findOrCreate(PackageItemInfo group, PackageManager pm, ArrayList<Preference> prefs)204     private PreferenceGroup findOrCreate(PackageItemInfo group, PackageManager pm,
205             ArrayList<Preference> prefs) {
206         PreferenceGroup pref = (PreferenceGroup) findPreference(group.name);
207         if (pref == null) {
208             pref = new PreferenceCategory(getActivity());
209             pref.setKey(group.name);
210             pref.setLayoutResource(R.layout.preference_category_material);
211             pref.setTitle(group.loadLabel(pm));
212             prefs.add(pref);
213             getPreferenceScreen().addPreference(pref);
214         }
215         return pref;
216     }
217 
getPreference(final PermissionInfo perm, final PermissionGroupInfo group)218     private Preference getPreference(final PermissionInfo perm, final PermissionGroupInfo group) {
219         if (isMutableGranularPermission(perm.name)) {
220             return getMutablePreference(perm, group);
221         } else {
222             return getImmutablePreference(perm, group);
223         }
224     }
225 
getMutablePreference(final PermissionInfo perm, PermissionGroupInfo group)226     private Preference getMutablePreference(final PermissionInfo perm, PermissionGroupInfo group) {
227         final AppPermissionGroup permGroup = mAppPermissions.getPermissionGroup(group.name);
228         final String[] filterPermissions = new String[]{perm.name};
229 
230         // TODO: No hardcoded layouts
231         SwitchPreference pref = new SwitchPreference(getPreferenceManager().getContext());
232         pref.setLayoutResource(R.layout.preference_permissions);
233         pref.setChecked(permGroup.areRuntimePermissionsGranted(filterPermissions));
234         pref.setIcon(getTintedPermissionIcon(getActivity(), perm, group));
235         pref.setTitle(perm.loadLabel(getActivity().getPackageManager()));
236         pref.setPersistent(false);
237 
238         pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
239             @Override
240             public boolean onPreferenceChange(Preference preference, Object value) {
241                 if (value == Boolean.TRUE) {
242                     permGroup.grantRuntimePermissions(false, filterPermissions);
243                 } else {
244                     permGroup.revokeRuntimePermissions(false, filterPermissions);
245                 }
246                 return true;
247             }
248         });
249 
250         return pref;
251     }
252 
getImmutablePreference(final PermissionInfo perm, PermissionGroupInfo group)253     private Preference getImmutablePreference(final PermissionInfo perm,
254             PermissionGroupInfo group) {
255         final PackageManager pm = getActivity().getPackageManager();
256 
257         // TODO: No hardcoded layouts
258         Preference pref = new Preference(getActivity());
259         pref.setLayoutResource(R.layout.preference_permissions);
260         pref.setIcon(getTintedPermissionIcon(getActivity(), perm, group));
261         pref.setTitle(perm.loadLabel(pm));
262         pref.setPersistent(false);
263 
264         pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
265             @Override
266             public boolean onPreferenceClick(Preference preference) {
267                 new AlertDialog.Builder(getActivity())
268                         .setMessage(perm.loadDescription(pm))
269                         .setPositiveButton(android.R.string.ok, null)
270                         .show();
271                 return true;
272             }
273         });
274 
275         return pref;
276     }
277 
getTintedPermissionIcon(Context context, PermissionInfo perm, PermissionGroupInfo group)278     private static Drawable getTintedPermissionIcon(Context context, PermissionInfo perm,
279             PermissionGroupInfo group) {
280         final Drawable icon;
281         if (perm.icon != 0) {
282             icon = perm.loadIcon(context.getPackageManager());
283         } else if (group != null && group.icon != 0) {
284             icon = group.loadIcon(context.getPackageManager());
285         } else {
286             icon =  context.getDrawable(R.drawable.ic_perm_device_info);
287         }
288         return Utils.applyTint(context, icon, android.R.attr.colorControlNormal);
289     }
290 
isMutableGranularPermission(String name)291     private static boolean isMutableGranularPermission(String name) {
292         if (!Build.PERMISSIONS_REVIEW_REQUIRED) {
293             return false;
294         }
295         switch (name) {
296             case Manifest.permission.READ_CONTACTS:
297             case Manifest.permission.WRITE_CONTACTS:
298             case Manifest.permission.READ_SMS:
299             case Manifest.permission.READ_CALL_LOG:
300             case Manifest.permission.CALL_PHONE: {
301                 return true;
302             }
303         }
304         return false;
305     }
306 }