1 /* 2 * Copyright (C) 2018 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.handheld; 18 19 import static com.android.packageinstaller.Constants.EXTRA_SESSION_ID; 20 21 import android.content.Context; 22 import android.content.Intent; 23 import android.graphics.drawable.Drawable; 24 import android.text.TextUtils; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.view.ViewGroup; 28 import android.widget.ImageView; 29 import android.widget.TextView; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 import androidx.preference.Preference; 34 import androidx.preference.PreferenceViewHolder; 35 36 import com.android.packageinstaller.permission.model.AppPermissionGroup; 37 import com.android.packageinstaller.permission.ui.AppPermissionActivity; 38 import com.android.permissioncontroller.R; 39 40 import java.util.List; 41 42 /** 43 * A preference that links to the screen where a permission can be toggled. 44 */ 45 public class PermissionControlPreference extends Preference { 46 private final @NonNull Context mContext; 47 private @Nullable Drawable mWidgetIcon; 48 private boolean mUseSmallerIcon; 49 private boolean mEllipsizeEnd; 50 private @Nullable List<Integer> mTitleIcons; 51 private @Nullable List<Integer> mSummaryIcons; 52 PermissionControlPreference(@onNull Context context, @NonNull AppPermissionGroup group, @NonNull String caller)53 public PermissionControlPreference(@NonNull Context context, 54 @NonNull AppPermissionGroup group, @NonNull String caller) { 55 this(context, group, caller, 0); 56 } 57 PermissionControlPreference(@onNull Context context, @NonNull AppPermissionGroup group, @NonNull String caller, long sessionId)58 public PermissionControlPreference(@NonNull Context context, 59 @NonNull AppPermissionGroup group, @NonNull String caller, long sessionId) { 60 super(context); 61 mContext = context; 62 mWidgetIcon = null; 63 mUseSmallerIcon = false; 64 mEllipsizeEnd = false; 65 mTitleIcons = null; 66 mSummaryIcons = null; 67 setOnPreferenceClickListener(preference -> { 68 Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION); 69 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, group.getApp().packageName); 70 intent.putExtra(Intent.EXTRA_PERMISSION_NAME, group.getPermissions().get(0).getName()); 71 intent.putExtra(Intent.EXTRA_USER, group.getUser()); 72 intent.putExtra(AppPermissionActivity.EXTRA_CALLER_NAME, caller); 73 intent.putExtra(EXTRA_SESSION_ID, sessionId); 74 context.startActivity(intent); 75 return true; 76 }); 77 } 78 79 /** 80 * Sets this preference's right icon. 81 * 82 * Note that this must be called before preference layout to take effect. 83 * 84 * @param widgetIcon the icon to use. 85 */ setRightIcon(@onNull Drawable widgetIcon)86 public void setRightIcon(@NonNull Drawable widgetIcon) { 87 mWidgetIcon = widgetIcon; 88 setWidgetLayoutResource(R.layout.image_view); 89 } 90 91 /** 92 * Sets this preference's left icon to be smaller than normal. 93 * 94 * Note that this must be called before preference layout to take effect. 95 */ useSmallerIcon()96 public void useSmallerIcon() { 97 mUseSmallerIcon = true; 98 } 99 100 /** 101 * Sets this preference's title to use an ellipsis at the end. 102 * 103 * Note that this must be called before preference layout to take effect. 104 */ setEllipsizeEnd()105 public void setEllipsizeEnd() { 106 mEllipsizeEnd = true; 107 } 108 109 /** 110 * Sets this preference's summary based on the group it represents, if applicable. 111 * 112 * @param group the permission group this preference represents. 113 */ setGroupSummary(@onNull AppPermissionGroup group)114 public void setGroupSummary(@NonNull AppPermissionGroup group) { 115 if (group.hasPermissionWithBackgroundMode() && group.areRuntimePermissionsGranted()) { 116 AppPermissionGroup backgroundGroup = group.getBackgroundPermissions(); 117 if (backgroundGroup == null || !backgroundGroup.areRuntimePermissionsGranted()) { 118 setSummary(R.string.permission_subtitle_only_in_foreground); 119 return; 120 } 121 } 122 setSummary(""); 123 } 124 125 /** 126 * Sets this preference to show the given icons to the left of its title. 127 * 128 * @param titleIcons the icons to show. 129 */ setTitleIcons(@onNull List<Integer> titleIcons)130 public void setTitleIcons(@NonNull List<Integer> titleIcons) { 131 mTitleIcons = titleIcons; 132 setLayoutResource(R.layout.preference_usage); 133 } 134 135 /** 136 * Sets this preference to show the given icons to the left of its summary. 137 * 138 * @param summaryIcons the icons to show. 139 */ setSummaryIcons(@onNull List<Integer> summaryIcons)140 public void setSummaryIcons(@NonNull List<Integer> summaryIcons) { 141 mSummaryIcons = summaryIcons; 142 setLayoutResource(R.layout.preference_usage); 143 } 144 145 @Override onBindViewHolder(PreferenceViewHolder holder)146 public void onBindViewHolder(PreferenceViewHolder holder) { 147 if (mUseSmallerIcon) { 148 ImageView icon = ((ImageView) holder.findViewById(android.R.id.icon)); 149 icon.setMaxWidth( 150 mContext.getResources().getDimensionPixelSize(R.dimen.secondary_app_icon_size)); 151 icon.setMaxHeight( 152 mContext.getResources().getDimensionPixelSize(R.dimen.secondary_app_icon_size)); 153 } 154 155 super.onBindViewHolder(holder); 156 157 if (mWidgetIcon != null) { 158 View widgetFrame = holder.findViewById(android.R.id.widget_frame); 159 ((ImageView) widgetFrame.findViewById(R.id.icon)).setImageDrawable(mWidgetIcon); 160 } 161 162 if (mEllipsizeEnd) { 163 TextView title = (TextView) holder.findViewById(android.R.id.title); 164 title.setMaxLines(1); 165 title.setEllipsize(TextUtils.TruncateAt.END); 166 } 167 168 setIcons(holder, mSummaryIcons, R.id.summary_widget_frame); 169 setIcons(holder, mTitleIcons, R.id.title_widget_frame); 170 } 171 setIcons(PreferenceViewHolder holder, @Nullable List<Integer> icons, int frameId)172 private void setIcons(PreferenceViewHolder holder, @Nullable List<Integer> icons, int frameId) { 173 ViewGroup frame = (ViewGroup) holder.findViewById(frameId); 174 if (icons != null && !icons.isEmpty()) { 175 frame.setVisibility(View.VISIBLE); 176 frame.removeAllViews(); 177 int numIcons = icons.size(); 178 for (int i = 0; i < numIcons; i++) { 179 LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class); 180 ViewGroup group = (ViewGroup) inflater.inflate(R.layout.title_summary_image_view, 181 null); 182 ImageView imageView = group.requireViewById(R.id.icon); 183 imageView.setImageResource(icons.get(i)); 184 frame.addView(group); 185 } 186 } else if (frame != null) { 187 frame.setVisibility(View.GONE); 188 } 189 } 190 } 191