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 package com.android.permissioncontroller.permission.ui.handheld; 17 18 import android.app.ActionBar; 19 import android.content.Context; 20 import android.os.Bundle; 21 import android.widget.ImageView; 22 23 import androidx.preference.Preference; 24 import androidx.preference.PreferenceScreen; 25 import androidx.preference.PreferenceViewHolder; 26 27 import com.android.permissioncontroller.R; 28 import com.android.permissioncontroller.permission.model.livedatatypes.PermGroupPackagesUiInfo; 29 import com.android.permissioncontroller.permission.utils.KotlinUtils; 30 import com.android.permissioncontroller.permission.utils.Utils; 31 32 import java.text.Collator; 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 38 /** 39 * Superclass for fragments allowing the user to manage permissions. 40 */ 41 abstract class ManagePermissionsFragment extends PermissionsFrameFragment 42 implements Preference.OnPreferenceClickListener { 43 private static final String LOG_TAG = "ManagePermissionsFragment"; 44 45 /** 46 * Map<permission names, PermGroupPackagesUiInfo>, representing the data about which 47 * apps are in which permission groups, which to show, and which are granted. 48 */ 49 protected Map<String, PermGroupPackagesUiInfo> mPermissionGroups = new HashMap<>(); 50 private Collator mCollator; 51 52 @Override onCreate(Bundle icicle)53 public void onCreate(Bundle icicle) { 54 super.onCreate(icicle); 55 setHasOptionsMenu(true); 56 final ActionBar ab = getActivity().getActionBar(); 57 if (ab != null) { 58 ab.setDisplayHomeAsUpEnabled(true); 59 } 60 61 mCollator = Collator.getInstance( 62 getContext().getResources().getConfiguration().getLocales().get(0)); 63 } 64 65 @Override onPreferenceClick(Preference preference)66 public boolean onPreferenceClick(Preference preference) { 67 String key = preference.getKey(); 68 69 PermGroupPackagesUiInfo group = mPermissionGroups.get(key); 70 if (group == null) { 71 return false; 72 } 73 74 showPermissionApps(key); 75 76 return true; 77 } 78 showPermissionApps(String permissionGroupName)79 abstract void showPermissionApps(String permissionGroupName); 80 81 /** 82 * Add preferences for all permissions of a type to the preference screen. 83 * 84 * @return The preference screen the permissions were added to 85 */ updatePermissionsUi()86 protected PreferenceScreen updatePermissionsUi() { 87 Context context = getPreferenceManager().getContext(); 88 if (context == null || getActivity() == null) { 89 return null; 90 } 91 92 if (mPermissionGroups == null) { 93 return null; 94 } 95 96 PreferenceScreen screen = getPreferenceScreen(); 97 if (screen == null) { 98 screen = getPreferenceManager().createPreferenceScreen(context); 99 setPreferenceScreen(screen); 100 } 101 102 List<Preference> toRemove = new ArrayList<>(); 103 for (int i = screen.getPreferenceCount() - 1; i >= 0; i--) { 104 Preference group = screen.getPreference(i); 105 if (!mPermissionGroups.containsKey(group.getKey())) { 106 toRemove.add(group); 107 } 108 } 109 110 for (Preference pref: toRemove) { 111 screen.removePreference(pref); 112 } 113 114 for (String groupName : mPermissionGroups.keySet()) { 115 116 PermGroupPackagesUiInfo group = mPermissionGroups.get(groupName); 117 118 Preference preference = findPreference(groupName); 119 120 if (preference == null) { 121 preference = new FixedSizeIconPreference(context); 122 preference.setOnPreferenceClickListener(this); 123 preference.setKey(groupName); 124 preference.setIcon(Utils.applyTint(context, 125 KotlinUtils.INSTANCE.getPermGroupIcon(context, groupName), 126 android.R.attr.colorControlNormal)); 127 preference.setTitle(KotlinUtils.INSTANCE.getPermGroupLabel(context, groupName)); 128 // Set blank summary so that no resizing/jumping happens when the summary is 129 // loaded. 130 preference.setSummary(" "); 131 preference.setPersistent(false); 132 screen.addPreference(preference); 133 } 134 String summary; 135 if (group != null) { 136 if (getResources().getBoolean(R.bool.config_useAlternativePermGroupSummary)) { 137 summary = getString(R.string.app_permissions_group_summary2, 138 group.getNonSystemGranted(), group.getNonSystemTotal()); 139 } else { 140 summary = getString(R.string.app_permissions_group_summary, 141 group.getNonSystemGranted(), group.getNonSystemTotal()); 142 } 143 } else { 144 summary = getString(R.string.loading); 145 } 146 preference.setSummary(summary); 147 } 148 149 KotlinUtils.INSTANCE.sortPreferenceGroup(screen, (Preference lhs, Preference rhs) -> 150 mCollator.compare(lhs.getTitle().toString(), rhs.getTitle().toString()), 151 false 152 ); 153 154 return screen; 155 } 156 157 /** 158 * A preference whose icons have the same fixed size. Allows the setting of dividers above and 159 * below the preference. 160 */ 161 protected static final class FixedSizeIconPreference extends Preference { 162 private boolean mShowDividerAbove = true; 163 private boolean mShowDividerBelow = false; 164 FixedSizeIconPreference(Context context)165 FixedSizeIconPreference(Context context) { 166 super(context); 167 } 168 FixedSizeIconPreference(Context context, boolean dividerAbove, boolean dividerBelow)169 FixedSizeIconPreference(Context context, boolean dividerAbove, boolean dividerBelow) { 170 super(context); 171 mShowDividerAbove = dividerAbove; 172 mShowDividerBelow = dividerBelow; 173 } 174 175 @Override onBindViewHolder(PreferenceViewHolder holder)176 public void onBindViewHolder(PreferenceViewHolder holder) { 177 super.onBindViewHolder(holder); 178 ImageView icon = ((ImageView) holder.findViewById(android.R.id.icon)); 179 icon.setAdjustViewBounds(true); 180 int size = getContext().getResources().getDimensionPixelSize( 181 R.dimen.permission_icon_size); 182 icon.setMaxWidth(size); 183 icon.setMaxHeight(size); 184 icon.getLayoutParams().width = size; 185 icon.getLayoutParams().height = size; 186 icon.setScaleType(ImageView.ScaleType.FIT_CENTER); 187 188 holder.setDividerAllowedAbove(mShowDividerAbove); 189 holder.setDividerAllowedBelow(mShowDividerBelow); 190 } 191 } 192 } 193