• 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.content.Context;
20 import android.content.Intent;
21 import android.graphics.drawable.Drawable;
22 import android.os.Bundle;
23 import android.util.ArrayMap;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 import androidx.fragment.app.Fragment;
28 import androidx.preference.Preference;
29 import androidx.preference.PreferenceCategory;
30 import androidx.preference.PreferenceGroup;
31 
32 import com.android.packageinstaller.auto.AutoSettingsFrameFragment;
33 import com.android.packageinstaller.permission.model.AppPermissionGroup;
34 import com.android.packageinstaller.permission.model.PermissionApps;
35 import com.android.packageinstaller.permission.model.PermissionApps.Callback;
36 import com.android.packageinstaller.permission.ui.handheld.PermissionAppsFragment;
37 import com.android.packageinstaller.permission.ui.handheld.PermissionControlPreference;
38 import com.android.packageinstaller.permission.utils.Utils;
39 import com.android.permissioncontroller.R;
40 
41 import java.text.Collator;
42 import java.util.ArrayList;
43 import java.util.Map;
44 
45 /** Shows the list of applications which have (or do not have) the given permission. */
46 public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implements Callback {
47 
48     private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem";
49     private static final String KEY_ALLOWED_PERMISSIONS_GROUP = "allowed_permissions_group";
50     private static final String KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP =
51             "allowed_foreground_permissions_group";
52     private static final String KEY_DENIED_PERMISSIONS_GROUP = "denied_permissions_group";
53 
54     private static final String SHOW_SYSTEM_KEY = AutoPermissionAppsFragment.class.getName()
55             + KEY_SHOW_SYSTEM_PREFS;
56 
57     /** Creates a new instance of {@link AutoPermissionAppsFragment} for the given permission. */
newInstance(String permissionName)58     public static AutoPermissionAppsFragment newInstance(String permissionName) {
59         return setPermissionName(new AutoPermissionAppsFragment(), permissionName);
60     }
61 
setPermissionName(T fragment, String permissionName)62     private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) {
63         Bundle arguments = new Bundle();
64         arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName);
65         fragment.setArguments(arguments);
66         return fragment;
67     }
68 
69     private PermissionApps mPermissionApps;
70 
71     private boolean mShowSystem;
72     private boolean mHasSystemApps;
73 
74     private Collator mCollator;
75 
76     @Override
onCreate(@ullable Bundle savedInstanceState)77     public void onCreate(@Nullable Bundle savedInstanceState) {
78         super.onCreate(savedInstanceState);
79 
80         if (savedInstanceState != null) {
81             mShowSystem = savedInstanceState.getBoolean(SHOW_SYSTEM_KEY);
82         }
83 
84         setLoading(true);
85 
86         String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME);
87         mPermissionApps = new PermissionApps(getActivity(), groupName, /* callback= */ this);
88         mPermissionApps.refresh(/* getUiInfo= */ true);
89 
90         mCollator = Collator.getInstance(
91                 getContext().getResources().getConfiguration().getLocales().get(0));
92 
93         setShowSystemAppsToggle();
94         bindUi(mPermissionApps, groupName);
95     }
96 
97     @Override
onCreatePreferences(Bundle bundle, String s)98     public void onCreatePreferences(Bundle bundle, String s) {
99         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
100     }
101 
102     @Override
onSaveInstanceState(Bundle outState)103     public void onSaveInstanceState(Bundle outState) {
104         super.onSaveInstanceState(outState);
105 
106         outState.putBoolean(SHOW_SYSTEM_KEY, mShowSystem);
107     }
108 
109     @Override
onStart()110     public void onStart() {
111         super.onStart();
112         mPermissionApps.refresh(/* getUiInfo= */ true);
113     }
114 
setShowSystemAppsToggle()115     private void setShowSystemAppsToggle() {
116         if (!mHasSystemApps) {
117             setAction(/* label= */ null, /* onClickListener= */ null);
118             return;
119         }
120 
121         // Show the opposite label from the current state.
122         String label;
123         if (mShowSystem) {
124             label = getString(R.string.menu_hide_system);
125         } else {
126             label = getString(R.string.menu_show_system);
127         }
128 
129         setAction(label, v -> {
130             mShowSystem = !mShowSystem;
131             if (mPermissionApps.getApps() != null) {
132                 onPermissionsLoaded(mPermissionApps);
133             }
134             setShowSystemAppsToggle();
135         });
136     }
137 
bindUi(PermissionApps permissionApps, @NonNull String groupName)138     private void bindUi(PermissionApps permissionApps, @NonNull String groupName) {
139         CharSequence label = permissionApps.getFullLabel();
140         setHeaderLabel(label);
141 
142         Drawable icon = permissionApps.getIcon();
143         Preference header = new Preference(getContext());
144         header.setTitle(label);
145         header.setIcon(icon);
146         header.setSummary(Utils.getPermissionGroupDescriptionString(getContext(), groupName,
147                 permissionApps.getDescription()));
148         getPreferenceScreen().addPreference(header);
149 
150         PreferenceGroup allowed = new PreferenceCategory(getContext());
151         allowed.setKey(KEY_ALLOWED_PERMISSIONS_GROUP);
152         allowed.setTitle(R.string.allowed_header);
153         allowed.setVisible(false);
154         getPreferenceScreen().addPreference(allowed);
155 
156         PreferenceGroup foreground = new PreferenceCategory(getContext());
157         foreground.setKey(KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP);
158         foreground.setTitle(R.string.allowed_foreground_header);
159         foreground.setVisible(false);
160         getPreferenceScreen().addPreference(foreground);
161 
162         PreferenceGroup denied = new PreferenceCategory(getContext());
163         denied.setKey(KEY_DENIED_PERMISSIONS_GROUP);
164         denied.setTitle(R.string.denied_header);
165         denied.setVisible(false);
166         getPreferenceScreen().addPreference(denied);
167     }
168 
169     @Override
onPermissionsLoaded(PermissionApps permissionApps)170     public void onPermissionsLoaded(PermissionApps permissionApps) {
171         Context context = getPreferenceManager().getContext();
172 
173         if (context == null || getActivity() == null) {
174             return;
175         }
176 
177         PreferenceCategory allowed = findPreference(KEY_ALLOWED_PERMISSIONS_GROUP);
178         PreferenceCategory allowedForeground = findPreference(
179                 KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP);
180         PreferenceCategory denied = findPreference(KEY_DENIED_PERMISSIONS_GROUP);
181 
182         allowed.setOrderingAsAdded(true);
183         allowedForeground.setOrderingAsAdded(true);
184         denied.setOrderingAsAdded(true);
185 
186         Map<String, Preference> existingPrefs = new ArrayMap<>();
187         int numPreferences = allowed.getPreferenceCount();
188         for (int i = 0; i < numPreferences; i++) {
189             Preference preference = allowed.getPreference(i);
190             existingPrefs.put(preference.getKey(), preference);
191         }
192         allowed.removeAll();
193         numPreferences = allowedForeground.getPreferenceCount();
194         for (int i = 0; i < numPreferences; i++) {
195             Preference preference = allowedForeground.getPreference(i);
196             existingPrefs.put(preference.getKey(), preference);
197         }
198         allowedForeground.removeAll();
199         numPreferences = denied.getPreferenceCount();
200         for (int i = 0; i < numPreferences; i++) {
201             Preference preference = denied.getPreference(i);
202             existingPrefs.put(preference.getKey(), preference);
203         }
204         denied.removeAll();
205 
206         mHasSystemApps = false;
207         boolean hasPermissionWithBackgroundMode = false;
208 
209         ArrayList<PermissionApps.PermissionApp> sortedApps = new ArrayList<>(
210                 permissionApps.getApps());
211         sortedApps.sort((x, y) -> {
212             int result = mCollator.compare(x.getLabel(), y.getLabel());
213             if (result == 0) {
214                 result = x.getUid() - y.getUid();
215             }
216             return result;
217         });
218 
219         for (int i = 0; i < sortedApps.size(); i++) {
220             PermissionApps.PermissionApp app = sortedApps.get(i);
221             AppPermissionGroup group = app.getPermissionGroup();
222 
223             hasPermissionWithBackgroundMode =
224                     hasPermissionWithBackgroundMode || group.hasPermissionWithBackgroundMode();
225 
226             if (!Utils.shouldShowPermission(getContext(), group)) {
227                 continue;
228             }
229 
230             if (!app.getAppInfo().enabled) {
231                 continue;
232             }
233 
234             String key = app.getKey();
235             Preference existingPref = existingPrefs.get(key);
236             if (existingPref != null) {
237                 // Without this, existing preferences remember their old order.
238                 existingPref.setOrder(Preference.DEFAULT_ORDER);
239             }
240 
241             boolean isSystemApp = !Utils.isGroupOrBgGroupUserSensitive(group);
242 
243             if (isSystemApp) {
244                 mHasSystemApps = true;
245             }
246 
247             if (isSystemApp && !mShowSystem) {
248                 continue;
249             }
250 
251             PreferenceCategory category;
252             if (group.areRuntimePermissionsGranted()) {
253                 if (!group.hasPermissionWithBackgroundMode()
254                         || (group.getBackgroundPermissions() != null
255                         && group.getBackgroundPermissions().areRuntimePermissionsGranted())) {
256                     category = allowed;
257                 } else {
258                     category = allowedForeground;
259                 }
260             } else {
261                 category = denied;
262             }
263 
264             if (existingPref != null) {
265                 category.addPreference(existingPref);
266                 continue;
267             }
268 
269             PermissionControlPreference pref = new PermissionControlPreference(context, group,
270                     PermissionAppsFragment.class.getName());
271             pref.setKey(key);
272             pref.setIcon(app.getIcon());
273             pref.setTitle(Utils.getFullAppLabel(app.getAppInfo(), context));
274             pref.setEllipsizeEnd();
275             pref.useSmallerIcon();
276             category.addPreference(pref);
277         }
278 
279         if (hasPermissionWithBackgroundMode) {
280             allowed.setTitle(R.string.allowed_always_header);
281         }
282 
283         if (allowed.getPreferenceCount() == 0) {
284             Preference empty = new Preference(context);
285             empty.setTitle(R.string.no_apps_allowed);
286             empty.setSelectable(false);
287             allowed.addPreference(empty);
288         }
289         allowed.setVisible(true);
290 
291         allowedForeground.setVisible(allowedForeground.getPreferenceCount() > 0);
292 
293         if (denied.getPreferenceCount() == 0) {
294             Preference empty = new Preference(context);
295             empty.setTitle(R.string.no_apps_denied);
296             empty.setSelectable(false);
297             denied.addPreference(empty);
298         }
299         denied.setVisible(true);
300 
301         setShowSystemAppsToggle();
302         setLoading(false);
303     }
304 }
305