• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.auto;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageInfo;
23 import android.graphics.drawable.Drawable;
24 import android.os.Bundle;
25 import android.os.UserHandle;
26 import android.widget.Toast;
27 
28 import androidx.annotation.NonNull;
29 import androidx.fragment.app.Fragment;
30 import androidx.preference.Preference;
31 import androidx.preference.PreferenceCategory;
32 import androidx.preference.PreferenceGroup;
33 import androidx.preference.PreferenceScreen;
34 
35 import com.android.packageinstaller.auto.AutoSettingsFrameFragment;
36 import com.android.packageinstaller.permission.model.AppPermissionGroup;
37 import com.android.packageinstaller.permission.model.AppPermissions;
38 import com.android.packageinstaller.permission.ui.AppPermissionActivity;
39 import com.android.packageinstaller.permission.utils.Utils;
40 import com.android.permissioncontroller.R;
41 
42 import java.text.Collator;
43 import java.util.ArrayList;
44 
45 /** Screen to show the permissions for a specific application. */
46 public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
47 
48     private static final String KEY_ALLOWED_PERMISSIONS_GROUP = "allowed_permissions_group";
49     private static final String KEY_DENIED_PERMISSIONS_GROUP = "denied_permissions_group";
50 
51     private AppPermissions mAppPermissions;
52     private PreferenceScreen mExtraScreen;
53 
54     private Collator mCollator;
55 
56     /**
57      * @return A new fragment
58      */
newInstance(@onNull String packageName, @NonNull UserHandle userHandle)59     public static AutoAppPermissionsFragment newInstance(@NonNull String packageName,
60             @NonNull UserHandle userHandle) {
61         return setPackageNameAndUserHandle(new AutoAppPermissionsFragment(), packageName,
62                 userHandle);
63     }
64 
setPackageNameAndUserHandle(@onNull T fragment, @NonNull String packageName, @NonNull UserHandle userHandle)65     private static <T extends Fragment> T setPackageNameAndUserHandle(@NonNull T fragment,
66             @NonNull String packageName, @NonNull UserHandle userHandle) {
67         Bundle arguments = new Bundle();
68         arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
69         arguments.putParcelable(Intent.EXTRA_USER, userHandle);
70         fragment.setArguments(arguments);
71         return fragment;
72     }
73 
74     @Override
onCreate(Bundle savedInstanceState)75     public void onCreate(Bundle savedInstanceState) {
76         super.onCreate(savedInstanceState);
77         setLoading(true);
78 
79         String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
80         UserHandle userHandle = getArguments().getParcelable(Intent.EXTRA_USER);
81         Activity activity = requireActivity();
82         PackageInfo packageInfo = AutoPermissionsUtils.getPackageInfo(activity, packageName,
83                 userHandle);
84         if (packageInfo == null) {
85             Toast.makeText(getContext(), R.string.app_not_found_dlg_title,
86                     Toast.LENGTH_LONG).show();
87             activity.finish();
88             return;
89         }
90 
91         setHeaderLabel(getContext().getString(R.string.app_permissions));
92         setAction(getContext().getString(R.string.all_permissions), v -> showAllPermissions());
93 
94         mAppPermissions = new AppPermissions(activity, packageInfo, /* sortGroups= */ true,
95                 () -> getActivity().finish());
96 
97         mCollator = Collator.getInstance(
98                 getContext().getResources().getConfiguration().getLocales().get(0));
99     }
100 
101     @Override
onCreatePreferences(Bundle bundle, String s)102     public void onCreatePreferences(Bundle bundle, String s) {
103         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
104     }
105 
106     @Override
onStart()107     public void onStart() {
108         super.onStart();
109         mAppPermissions.refresh();
110         bindUi(mAppPermissions.getPackageInfo());
111         updatePreferences();
112     }
113 
114     @Override
onStop()115     public void onStop() {
116         super.onStop();
117         getPreferenceScreen().removeAll();
118     }
119 
showAllPermissions()120     private void showAllPermissions() {
121         Fragment frag = AutoAllAppPermissionsFragment.newInstance(
122                 getArguments().getString(Intent.EXTRA_PACKAGE_NAME),
123                 getArguments().getParcelable(Intent.EXTRA_USER));
124         getFragmentManager().beginTransaction()
125                 .replace(android.R.id.content, frag)
126                 .addToBackStack("AllPerms")
127                 .commit();
128     }
129 
bindUi(PackageInfo packageInfo)130     protected void bindUi(PackageInfo packageInfo) {
131         getPreferenceScreen().addPreference(
132                 AutoPermissionsUtils.createHeaderPreference(getContext(),
133                         packageInfo.applicationInfo));
134 
135         PreferenceGroup allowed = new PreferenceCategory(getContext());
136         allowed.setKey(KEY_ALLOWED_PERMISSIONS_GROUP);
137         allowed.setTitle(R.string.allowed_header);
138         getPreferenceScreen().addPreference(allowed);
139 
140         PreferenceGroup denied = new PreferenceCategory(getContext());
141         denied.setKey(KEY_DENIED_PERMISSIONS_GROUP);
142         denied.setTitle(R.string.denied_header);
143         getPreferenceScreen().addPreference(denied);
144     }
145 
updatePreferences()146     private void updatePreferences() {
147         Context context = getPreferenceManager().getContext();
148         if (context == null) {
149             return;
150         }
151 
152         PreferenceCategory allowed = findPreference(KEY_ALLOWED_PERMISSIONS_GROUP);
153         PreferenceCategory denied = findPreference(KEY_DENIED_PERMISSIONS_GROUP);
154 
155         allowed.removeAll();
156         denied.removeAll();
157 
158         if (mExtraScreen != null) {
159             mExtraScreen.removeAll();
160             mExtraScreen.addPreference(AutoPermissionsUtils.createHeaderPreference(getContext(),
161                     mAppPermissions.getPackageInfo().applicationInfo));
162         }
163 
164         Preference extraPerms = new Preference(context);
165         extraPerms.setIcon(R.drawable.ic_toc);
166         extraPerms.setTitle(R.string.additional_permissions);
167         boolean extraPermsAreAllowed = false;
168 
169         ArrayList<AppPermissionGroup> groups = new ArrayList<>(
170                 mAppPermissions.getPermissionGroups());
171         groups.sort((x, y) -> mCollator.compare(x.getLabel(), y.getLabel()));
172         allowed.setOrderingAsAdded(true);
173         denied.setOrderingAsAdded(true);
174 
175         for (int i = 0; i < groups.size(); i++) {
176             AppPermissionGroup group = groups.get(i);
177             if (!Utils.shouldShowPermission(getContext(), group)) {
178                 continue;
179             }
180 
181             boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG);
182 
183             Preference preference = createPermissionPreference(getContext(), group);
184             if (isPlatform) {
185                 PreferenceCategory category =
186                         group.areRuntimePermissionsGranted() ? allowed : denied;
187                 category.addPreference(preference);
188             } else {
189                 if (mExtraScreen == null) {
190                     mExtraScreen = getPreferenceManager().createPreferenceScreen(context);
191                     mExtraScreen.addPreference(
192                             AutoPermissionsUtils.createHeaderPreference(getContext(),
193                                     mAppPermissions.getPackageInfo().applicationInfo));
194                 }
195                 mExtraScreen.addPreference(preference);
196                 if (group.areRuntimePermissionsGranted()) {
197                     extraPermsAreAllowed = true;
198                 }
199             }
200         }
201 
202         if (mExtraScreen != null) {
203             extraPerms.setOnPreferenceClickListener(preference -> {
204                 AutoAppPermissionsFragment.AdditionalPermissionsFragment
205                         frag = new AutoAppPermissionsFragment.AdditionalPermissionsFragment();
206                 setPackageNameAndUserHandle(frag,
207                         getArguments().getString(Intent.EXTRA_PACKAGE_NAME),
208                         getArguments().getParcelable(Intent.EXTRA_USER));
209                 frag.setTargetFragment(AutoAppPermissionsFragment.this, 0);
210                 getFragmentManager().beginTransaction()
211                         .replace(android.R.id.content, frag)
212                         .addToBackStack(null)
213                         .commit();
214                 return true;
215             });
216             // Delete 1 to account for app header preference.
217             int count = mExtraScreen.getPreferenceCount() - 1;
218             extraPerms.setSummary(getResources().getQuantityString(
219                     R.plurals.additional_permissions_more, count,
220                     count));
221             PreferenceCategory category = extraPermsAreAllowed ? allowed : denied;
222             category.addPreference(extraPerms);
223         }
224 
225         if (allowed.getPreferenceCount() == 0) {
226             Preference empty = new Preference(context);
227             empty.setTitle(getString(R.string.no_permissions_allowed));
228             empty.setSelectable(false);
229             allowed.addPreference(empty);
230         }
231         if (denied.getPreferenceCount() == 0) {
232             Preference empty = new Preference(context);
233             empty.setTitle(getString(R.string.no_permissions_denied));
234             empty.setSelectable(false);
235             denied.addPreference(empty);
236         }
237 
238         setLoading(false);
239     }
240 
createPermissionPreference(Context context, AppPermissionGroup group)241     private Preference createPermissionPreference(Context context, AppPermissionGroup group) {
242         Preference preference = new Preference(context);
243         Drawable icon = Utils.loadDrawable(context.getPackageManager(),
244                 group.getIconPkg(), group.getIconResId());
245         preference.setKey(group.getName());
246         preference.setTitle(group.getFullLabel());
247         preference.setIcon(Utils.applyTint(context, icon, android.R.attr.colorControlNormal));
248         preference.setOnPreferenceClickListener(pref -> {
249             Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
250             intent.putExtra(Intent.EXTRA_PACKAGE_NAME, group.getApp().packageName);
251             intent.putExtra(Intent.EXTRA_PERMISSION_NAME, group.getPermissions().get(0).getName());
252             intent.putExtra(Intent.EXTRA_USER, group.getUser());
253             intent.putExtra(AppPermissionActivity.EXTRA_CALLER_NAME,
254                     AutoAppPermissionsFragment.class.getName());
255             context.startActivity(intent);
256             return true;
257         });
258         return preference;
259     }
260 
getGroupSummary(AppPermissionGroup group)261     private String getGroupSummary(AppPermissionGroup group) {
262         if (group.hasPermissionWithBackgroundMode() && group.areRuntimePermissionsGranted()) {
263             AppPermissionGroup backgroundGroup = group.getBackgroundPermissions();
264             if (backgroundGroup == null || !backgroundGroup.areRuntimePermissionsGranted()) {
265                 return getContext().getString(R.string.permission_subtitle_only_in_foreground);
266             }
267         }
268         return null;
269     }
270 
271     /**
272      * Class that shows additional permissions.
273      */
274     public static class AdditionalPermissionsFragment extends AutoSettingsFrameFragment {
275         AutoAppPermissionsFragment mOuterFragment;
276 
277         @Override
onCreate(Bundle savedInstanceState)278         public void onCreate(Bundle savedInstanceState) {
279             // Set this before calling super.onCreate as it is needed in onCreatePreferences
280             // (which is called from super.onCreate).
281             mOuterFragment = (AutoAppPermissionsFragment) getTargetFragment();
282             super.onCreate(savedInstanceState);
283             setHeaderLabel(mOuterFragment.getHeaderLabel());
284         }
285 
286         @Override
onCreatePreferences(Bundle bundle, String s)287         public void onCreatePreferences(Bundle bundle, String s) {
288             setPreferenceScreen(mOuterFragment.mExtraScreen);
289         }
290     }
291 }
292 
293