summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/content/Intent.java4
-rwxr-xr-xcore/java/android/widget/AppSecurityPermissions.java592
-rw-r--r--core/res/res/layout/app_permission_item.xml37
-rw-r--r--core/res/res/layout/app_permission_item_old.xml55
-rwxr-xr-xcore/res/res/layout/app_perms_summary.xml79
-rw-r--r--core/res/res/values/public.xml9
-rwxr-xr-xcore/res/res/values/strings.xml2
7 files changed, 375 insertions, 403 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b4669a7..cb8fea2 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1240,7 +1240,11 @@ public class Intent implements Parcelable, Cloneable {
* Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
* package. Tells the installer UI to skip the confirmation with the user
* if the .apk is replacing an existing one.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, Android
+ * will no longer show an interstitial message about updating existing
+ * applications so this is no longer needed.
*/
+ @Deprecated
public static final String EXTRA_ALLOW_REPLACE
= "android.intent.extra.ALLOW_REPLACE";
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index b409e26..5d8bdbb 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -18,7 +18,9 @@ package android.widget;
import com.android.internal.R;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -27,14 +29,13 @@ import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
-import android.text.Spannable;
-import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
+import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import java.text.Collator;
import java.util.ArrayList;
@@ -42,7 +43,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -58,16 +58,51 @@ import java.util.Set;
*
* {@hide}
*/
-public class AppSecurityPermissions implements View.OnClickListener {
+public class AppSecurityPermissions {
- private enum State {
- NO_PERMS,
- DANGEROUS_ONLY,
- NORMAL_ONLY,
- BOTH
+ public static final int WHICH_PERSONAL = 1<<0;
+ public static final int WHICH_DEVICE = 1<<1;
+ public static final int WHICH_NEW = 1<<2;
+ public static final int WHICH_ALL = 0xffff;
+
+ private final static String TAG = "AppSecurityPermissions";
+ private boolean localLOGV = false;
+ private Context mContext;
+ private LayoutInflater mInflater;
+ private PackageManager mPm;
+ private PackageInfo mInstalledPackageInfo;
+ private final Map<String, MyPermissionGroupInfo> mPermGroups
+ = new HashMap<String, MyPermissionGroupInfo>();
+ private final List<MyPermissionGroupInfo> mPermGroupsList
+ = new ArrayList<MyPermissionGroupInfo>();
+ private final PermissionGroupInfoComparator mPermGroupComparator;
+ private final PermissionInfoComparator mPermComparator;
+ private List<MyPermissionInfo> mPermsList;
+ private CharSequence mNewPermPrefix;
+ private Drawable mNormalIcon;
+ private Drawable mDangerousIcon;
+
+ static class MyPermissionGroupInfo extends PermissionGroupInfo {
+ CharSequence mLabel;
+
+ final ArrayList<MyPermissionInfo> mNewPermissions = new ArrayList<MyPermissionInfo>();
+ final ArrayList<MyPermissionInfo> mPersonalPermissions = new ArrayList<MyPermissionInfo>();
+ final ArrayList<MyPermissionInfo> mDevicePermissions = new ArrayList<MyPermissionInfo>();
+ final ArrayList<MyPermissionInfo> mAllPermissions = new ArrayList<MyPermissionInfo>();
+
+ MyPermissionGroupInfo(PermissionInfo perm) {
+ name = perm.packageName;
+ packageName = perm.packageName;
+ }
+
+ MyPermissionGroupInfo(PermissionGroupInfo info) {
+ super(info);
+ }
}
static class MyPermissionInfo extends PermissionInfo {
+ CharSequence mLabel;
+
/**
* PackageInfo.requestedPermissionsFlags for the new package being installed.
*/
@@ -99,46 +134,99 @@ public class AppSecurityPermissions implements View.OnClickListener {
}
}
- private final static String TAG = "AppSecurityPermissions";
- private boolean localLOGV = false;
- private Context mContext;
- private LayoutInflater mInflater;
- private PackageManager mPm;
- private LinearLayout mPermsView;
- private Map<String, CharSequence> mNewMap;
- private Map<String, CharSequence> mDangerousMap;
- private Map<String, CharSequence> mNormalMap;
- private List<MyPermissionInfo> mPermsList;
- private String mDefaultGrpLabel;
- private String mDefaultGrpName="DefaultGrp";
- private String mPermFormat;
- private CharSequence mNewPermPrefix;
- private Drawable mNormalIcon;
- private Drawable mDangerousIcon;
- private boolean mExpanded;
- private Drawable mShowMaxIcon;
- private Drawable mShowMinIcon;
- private View mShowMore;
- private TextView mShowMoreText;
- private ImageView mShowMoreIcon;
- private State mCurrentState;
- private LinearLayout mNonDangerousList;
- private LinearLayout mDangerousList;
- private LinearLayout mNewList;
- private HashMap<String, CharSequence> mGroupLabelCache;
- private View mNoPermsView;
+ public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
+ MyPermissionGroupInfo mGroup;
+ MyPermissionInfo mPerm;
+ AlertDialog mDialog;
+
+ public PermissionItemView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setClickable(true);
+ }
+
+ public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
+ boolean first, CharSequence newPermPrefix) {
+ mGroup = grp;
+ mPerm = perm;
+
+ ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
+ TextView permNameView = (TextView) findViewById(R.id.perm_name);
+
+ PackageManager pm = getContext().getPackageManager();
+ Drawable icon = null;
+ if (first) {
+ if (grp.icon != 0) {
+ icon = grp.loadIcon(pm);
+ } else {
+ ApplicationInfo appInfo;
+ try {
+ appInfo = pm.getApplicationInfo(grp.packageName, 0);
+ icon = appInfo.loadIcon(pm);
+ } catch (NameNotFoundException e) {
+ }
+ }
+ }
+ CharSequence label = perm.mLabel;
+ if (perm.mNew && newPermPrefix != null) {
+ // If this is a new permission, format it appropriately.
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ Parcel parcel = Parcel.obtain();
+ TextUtils.writeToParcel(newPermPrefix, parcel, 0);
+ parcel.setDataPosition(0);
+ CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+ builder.append(newStr);
+ builder.append(label);
+ label = builder;
+ }
+
+ permGrpIcon.setImageDrawable(icon);
+ permNameView.setText(label);
+ setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mGroup != null && mPerm != null) {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle(mGroup.mLabel);
+ builder.setMessage(mPerm.loadDescription(getContext().getPackageManager()));
+ builder.setCancelable(true);
+ mDialog = builder.show();
+ mDialog.setCanceledOnTouchOutside(true);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+ }
public AppSecurityPermissions(Context context, List<PermissionInfo> permList) {
mContext = context;
mPm = mContext.getPackageManager();
+ loadResources();
+ mPermComparator = new PermissionInfoComparator();
+ mPermGroupComparator = new PermissionGroupInfoComparator();
for (PermissionInfo pi : permList) {
mPermsList.add(new MyPermissionInfo(pi));
}
+ setPermissions(mPermsList);
}
public AppSecurityPermissions(Context context, String packageName) {
mContext = context;
mPm = mContext.getPackageManager();
+ loadResources();
+ mPermComparator = new PermissionInfoComparator();
+ mPermGroupComparator = new PermissionGroupInfoComparator();
mPermsList = new ArrayList<MyPermissionInfo>();
Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
PackageInfo pkgInfo;
@@ -155,11 +243,15 @@ public class AppSecurityPermissions implements View.OnClickListener {
for(MyPermissionInfo tmpInfo : permSet) {
mPermsList.add(tmpInfo);
}
+ setPermissions(mPermsList);
}
-
+
public AppSecurityPermissions(Context context, PackageParser.Package pkg) {
mContext = context;
mPm = mContext.getPackageManager();
+ loadResources();
+ mPermComparator = new PermissionInfoComparator();
+ mPermGroupComparator = new PermissionGroupInfoComparator();
mPermsList = new ArrayList<MyPermissionInfo>();
Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
if(pkg == null) {
@@ -193,10 +285,20 @@ public class AppSecurityPermissions implements View.OnClickListener {
for (MyPermissionInfo tmpInfo : permSet) {
mPermsList.add(tmpInfo);
}
+ setPermissions(mPermsList);
}
-
+
+ private void loadResources() {
+ // Pick up from framework resources instead.
+ mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
+ mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
+ mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
+ }
+
/**
- * Utility to retrieve a view displaying a single permission.
+ * Utility to retrieve a view displaying a single permission. This provides
+ * the old UI layout for permissions; it is only here for the device admin
+ * settings to continue to use.
*/
public static View getPermissionItemView(Context context,
CharSequence grpName, CharSequence description, boolean dangerous) {
@@ -204,10 +306,14 @@ public class AppSecurityPermissions implements View.OnClickListener {
Context.LAYOUT_INFLATER_SERVICE);
Drawable icon = context.getResources().getDrawable(dangerous
? R.drawable.ic_bullet_key_permission : R.drawable.ic_text_dot);
- return getPermissionItemView(context, inflater, grpName,
+ return getPermissionItemViewOld(context, inflater, grpName,
description, dangerous, icon);
}
+ public PackageInfo getInstalledPackageInfo() {
+ return mInstalledPackageInfo;
+ }
+
private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
if(sharedPkgList == null || (sharedPkgList.length == 0)) {
@@ -239,6 +345,7 @@ public class AppSecurityPermissions implements View.OnClickListener {
if ((strList == null) || (strList.length == 0)) {
return;
}
+ mInstalledPackageInfo = installedPkgInfo;
for (int i=0; i<strList.length; i++) {
String permName = strList[i];
// If we are only looking at an existing app, then we only
@@ -270,13 +377,42 @@ public class AppSecurityPermissions implements View.OnClickListener {
// to see, so skip it.
continue;
}
+ final String origGroupName = tmpPermInfo.group;
+ String groupName = origGroupName;
+ if (groupName == null) {
+ groupName = tmpPermInfo.packageName;
+ tmpPermInfo.group = groupName;
+ }
+ MyPermissionGroupInfo group = mPermGroups.get(groupName);
+ if (group == null) {
+ PermissionGroupInfo grp = null;
+ if (origGroupName != null) {
+ grp = mPm.getPermissionGroupInfo(origGroupName, 0);
+ }
+ if (grp != null) {
+ group = new MyPermissionGroupInfo(grp);
+ } else {
+ // We could be here either because the permission
+ // didn't originally specify a group or the group it
+ // gave couldn't be found. In either case, we consider
+ // its group to be the permission's package name.
+ tmpPermInfo.group = tmpPermInfo.packageName;
+ group = mPermGroups.get(tmpPermInfo.group);
+ if (group == null) {
+ group = new MyPermissionGroupInfo(tmpPermInfo);
+ }
+ group = new MyPermissionGroupInfo(tmpPermInfo);
+ }
+ mPermGroups.put(tmpPermInfo.group, group);
+ }
+ final boolean newPerm = installedPkgInfo != null
+ && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
MyPermissionInfo myPerm = new MyPermissionInfo(tmpPermInfo);
myPerm.mNewReqFlags = flagsList[i];
myPerm.mExistingReqFlags = existingFlags;
// This is a new permission if the app is already installed and
// doesn't currently hold this permission.
- myPerm.mNew = installedPkgInfo != null
- && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
+ myPerm.mNew = newPerm;
permSet.add(myPerm);
} catch (NameNotFoundException e) {
Log.i(TAG, "Ignoring unknown permission:"+permName);
@@ -285,149 +421,99 @@ public class AppSecurityPermissions implements View.OnClickListener {
}
public int getPermissionCount() {
- return mPermsList.size();
+ return getPermissionCount(WHICH_ALL);
}
- public View getPermissionsView() {
-
- mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mPermsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- mShowMore = mPermsView.findViewById(R.id.show_more);
- mShowMoreIcon = (ImageView) mShowMore.findViewById(R.id.show_more_icon);
- mShowMoreText = (TextView) mShowMore.findViewById(R.id.show_more_text);
- mNewList = (LinearLayout) mPermsView.findViewById(R.id.new_perms_list);
- mDangerousList = (LinearLayout) mPermsView.findViewById(R.id.dangerous_perms_list);
- mNonDangerousList = (LinearLayout) mPermsView.findViewById(R.id.non_dangerous_perms_list);
- mNoPermsView = mPermsView.findViewById(R.id.no_permissions);
-
- // Set up the LinearLayout that acts like a list item.
- mShowMore.setClickable(true);
- mShowMore.setOnClickListener(this);
- mShowMore.setFocusable(true);
-
- // Pick up from framework resources instead.
- mDefaultGrpLabel = mContext.getString(R.string.default_permission_group);
- mPermFormat = mContext.getString(R.string.permissions_format);
- mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
- mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
- mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
- mShowMaxIcon = mContext.getResources().getDrawable(R.drawable.expander_close_holo_dark);
- mShowMinIcon = mContext.getResources().getDrawable(R.drawable.expander_open_holo_dark);
-
- // Set permissions view
- setPermissions(mPermsList);
- return mPermsView;
+ private List<MyPermissionInfo> getPermissionList(MyPermissionGroupInfo grp, int which) {
+ if (which == WHICH_NEW) {
+ return grp.mNewPermissions;
+ } else if (which == WHICH_PERSONAL) {
+ return grp.mPersonalPermissions;
+ } else if (which == WHICH_DEVICE) {
+ return grp.mDevicePermissions;
+ } else {
+ return grp.mAllPermissions;
+ }
}
- /**
- * Utility method that concatenates two strings defined by mPermFormat.
- * a null value is returned if both str1 and str2 are null, if one of the strings
- * is null the other non null value is returned without formatting
- * this is to placate initial error checks
- */
- private CharSequence formatPermissions(CharSequence groupDesc, CharSequence permDesc,
- boolean newPerms) {
- if (permDesc == null) {
- return groupDesc;
- }
- // Sometimes people write permission names with a trailing period;
- // strip that if it appears.
- int len = permDesc.length();
- if (len > 0 && permDesc.charAt(len-1) == '.') {
- permDesc = (permDesc.toString()).substring(0, len-1);
- }
- if (newPerms) {
- if (true) {
- // If this is a new permission, format it appropriately.
- SpannableStringBuilder builder = new SpannableStringBuilder();
- if (groupDesc != null) {
- // The previous permissions go in front, with a newline
- // separating them.
- builder.append(groupDesc);
- builder.append("\n");
- }
- Parcel parcel = Parcel.obtain();
- TextUtils.writeToParcel(mNewPermPrefix, parcel, 0);
- parcel.setDataPosition(0);
- CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- parcel.recycle();
- builder.append(newStr);
- builder.append(permDesc);
- return builder;
- } else {
- // If this is a new permission, format it appropriately.
- SpannableStringBuilder builder = new SpannableStringBuilder(permDesc);
- builder.insert(0, mNewPermPrefix);
- if (groupDesc != null) {
- // The previous permissions go in front, with a newline
- // separating them.
- builder.insert(0, "\n");
- builder.insert(0, groupDesc);
- }
- return builder;
- }
- }
- if (groupDesc == null) {
- return permDesc;
+ public int getPermissionCount(int which) {
+ int N = 0;
+ for (int i=0; i<mPermGroupsList.size(); i++) {
+ N += getPermissionList(mPermGroupsList.get(i), which).size();
}
- // groupDesc and permDesc are non null
- return String.format(mPermFormat, groupDesc, permDesc.toString());
+ return N;
}
- private CharSequence getGroupLabel(String grpName) {
- if (grpName == null) {
- //return default label
- return mDefaultGrpLabel;
- }
- CharSequence cachedLabel = mGroupLabelCache.get(grpName);
- if (cachedLabel != null) {
- return cachedLabel;
- }
- PermissionGroupInfo pgi;
- try {
- pgi = mPm.getPermissionGroupInfo(grpName, 0);
- } catch (NameNotFoundException e) {
- Log.i(TAG, "Invalid group name:" + grpName);
- return null;
+ public View getPermissionsView() {
+ return getPermissionsView(WHICH_ALL);
+ }
+
+ public View getPermissionsView(int which) {
+ mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
+ LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+ View noPermsView = permsView.findViewById(R.id.no_permissions);
+
+ displayPermissions(mPermGroupsList, displayList, which);
+ if (displayList.getChildCount() <= 0) {
+ noPermsView.setVisibility(View.VISIBLE);
}
- CharSequence label = pgi.loadLabel(mPm).toString();
- mGroupLabelCache.put(grpName, label);
- return label;
+
+ return permsView;
}
/**
* Utility method that displays permissions from a map containing group name and
* list of permission descriptions.
*/
- private void displayPermissions(Map<String, CharSequence> permInfoMap,
- LinearLayout permListView, boolean dangerous) {
+ private void displayPermissions(List<MyPermissionGroupInfo> groups,
+ LinearLayout permListView, int which) {
permListView.removeAllViews();
- Set<String> permInfoStrSet = permInfoMap.keySet();
- for (String loopPermGrpInfoStr : permInfoStrSet) {
- CharSequence grpLabel = getGroupLabel(loopPermGrpInfoStr);
- //guaranteed that grpLabel wont be null since permissions without groups
- //will belong to the default group
- if(localLOGV) Log.i(TAG, "Adding view group:" + grpLabel + ", desc:"
- + permInfoMap.get(loopPermGrpInfoStr));
- permListView.addView(getPermissionItemView(grpLabel,
- permInfoMap.get(loopPermGrpInfoStr), dangerous));
+ int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
+
+ for (int i=0; i<groups.size(); i++) {
+ MyPermissionGroupInfo grp = groups.get(i);
+ final List<MyPermissionInfo> perms = getPermissionList(grp, which);
+ for (int j=0; j<perms.size(); j++) {
+ MyPermissionInfo perm = perms.get(j);
+ View view = getPermissionItemView(grp, perm, j == 0,
+ which != WHICH_NEW ? mNewPermPrefix : null);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ if (j == 0) {
+ lp.topMargin = spacing;
+ }
+ if (j == grp.mAllPermissions.size()-1) {
+ lp.bottomMargin = spacing;
+ }
+ if (permListView.getChildCount() == 0) {
+ lp.topMargin *= 2;
+ }
+ permListView.addView(view, lp);
+ }
}
}
- private void displayNoPermissions() {
- mNoPermsView.setVisibility(View.VISIBLE);
+ private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
+ MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) {
+ return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix);
}
- private View getPermissionItemView(CharSequence grpName, CharSequence permList,
- boolean dangerous) {
- return getPermissionItemView(mContext, mInflater, grpName, permList,
- dangerous, dangerous ? mDangerousIcon : mNormalIcon);
+ private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
+ MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
+ CharSequence newPermPrefix) {
+ PermissionItemView permView = (PermissionItemView)inflater.inflate(
+ R.layout.app_permission_item, null);
+ permView.setPermission(grp, perm, first, newPermPrefix);
+ return permView;
}
- private static View getPermissionItemView(Context context, LayoutInflater inflater,
+ private static View getPermissionItemViewOld(Context context, LayoutInflater inflater,
CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
- View permView = inflater.inflate(R.layout.app_permission_item, null);
+ View permView = inflater.inflate(R.layout.app_permission_item_old, null);
TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
@@ -444,41 +530,6 @@ public class AppSecurityPermissions implements View.OnClickListener {
return permView;
}
- private void showPermissions() {
-
- switch(mCurrentState) {
- case NO_PERMS:
- displayNoPermissions();
- break;
-
- case DANGEROUS_ONLY:
- displayPermissions(mNewMap, mNewList, true);
- displayPermissions(mDangerousMap, mDangerousList, true);
- break;
-
- case NORMAL_ONLY:
- displayPermissions(mNewMap, mNewList, true);
- displayPermissions(mNormalMap, mNonDangerousList, false);
- break;
-
- case BOTH:
- displayPermissions(mNewMap, mNewList, true);
- displayPermissions(mDangerousMap, mDangerousList, true);
- if (mExpanded) {
- displayPermissions(mNormalMap, mNonDangerousList, false);
- mShowMoreIcon.setImageDrawable(mShowMaxIcon);
- mShowMoreText.setText(R.string.perms_hide);
- mNonDangerousList.setVisibility(View.VISIBLE);
- } else {
- mShowMoreIcon.setImageDrawable(mShowMinIcon);
- mShowMoreText.setText(R.string.perms_show_all);
- mNonDangerousList.setVisibility(View.GONE);
- }
- mShowMore.setVisibility(View.VISIBLE);
- break;
- }
- }
-
private boolean isDisplayablePermission(PermissionInfo pInfo, int newReqFlags,
int existingReqFlags) {
final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
@@ -496,79 +547,45 @@ public class AppSecurityPermissions implements View.OnClickListener {
}
return false;
}
-
- /*
- * Utility method that aggregates all permission descriptions categorized by group
- * Say group1 has perm11, perm12, perm13, the group description will be
- * perm11_Desc, perm12_Desc, perm13_Desc
- */
- private void aggregateGroupDescs(Map<String, List<MyPermissionInfo> > map,
- Map<String, CharSequence> retMap, boolean newPerms) {
- if(map == null) {
- return;
+
+ private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
+ private final Collator sCollator = Collator.getInstance();
+ PermissionGroupInfoComparator() {
}
- if(retMap == null) {
- return;
- }
- Set<String> grpNames = map.keySet();
- Iterator<String> grpNamesIter = grpNames.iterator();
- while(grpNamesIter.hasNext()) {
- CharSequence grpDesc = null;
- String grpNameKey = grpNamesIter.next();
- List<MyPermissionInfo> grpPermsList = map.get(grpNameKey);
- if(grpPermsList == null) {
- continue;
- }
- for(PermissionInfo permInfo: grpPermsList) {
- CharSequence permDesc = permInfo.loadLabel(mPm);
- grpDesc = formatPermissions(grpDesc, permDesc, newPerms);
+ public final int compare(MyPermissionGroupInfo a, MyPermissionGroupInfo b) {
+ if (((a.flags^b.flags)&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
+ return ((a.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) ? -1 : 1;
}
- // Insert grpDesc into map
- if(grpDesc != null) {
- if(localLOGV) Log.i(TAG, "Group:"+grpNameKey+" description:"+grpDesc.toString());
- retMap.put(grpNameKey, grpDesc);
+ if (a.priority != b.priority) {
+ return a.priority > b.priority ? -1 : 1;
}
+ return sCollator.compare(a.mLabel, b.mLabel);
}
}
- private static class PermissionInfoComparator implements Comparator<PermissionInfo> {
- private PackageManager mPm;
+ private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
private final Collator sCollator = Collator.getInstance();
- PermissionInfoComparator(PackageManager pm) {
- mPm = pm;
+ PermissionInfoComparator() {
}
- public final int compare(PermissionInfo a, PermissionInfo b) {
- CharSequence sa = a.loadLabel(mPm);
- CharSequence sb = b.loadLabel(mPm);
- return sCollator.compare(sa, sb);
+ public final int compare(MyPermissionInfo a, MyPermissionInfo b) {
+ return sCollator.compare(a.mLabel, b.mLabel);
}
}
-
+
+ private void addPermToList(List<MyPermissionInfo> permList,
+ MyPermissionInfo pInfo) {
+ if (pInfo.mLabel == null) {
+ pInfo.mLabel = pInfo.loadLabel(mPm);
+ }
+ int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
+ if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
+ if (idx < 0) {
+ idx = -idx-1;
+ permList.add(idx, pInfo);
+ }
+ }
+
private void setPermissions(List<MyPermissionInfo> permList) {
- mGroupLabelCache = new HashMap<String, CharSequence>();
- //add the default label so that uncategorized permissions can go here
- mGroupLabelCache.put(mDefaultGrpName, mDefaultGrpLabel);
-
- // Map containing group names and a list of permissions under that group
- // that are new from the current install
- mNewMap = new HashMap<String, CharSequence>();
- // Map containing group names and a list of permissions under that group
- // categorized as dangerous
- mDangerousMap = new HashMap<String, CharSequence>();
- // Map containing group names and a list of permissions under that group
- // categorized as normal
- mNormalMap = new HashMap<String, CharSequence>();
-
- // Additional structures needed to ensure that permissions are unique under
- // each group
- Map<String, List<MyPermissionInfo>> newMap =
- new HashMap<String, List<MyPermissionInfo>>();
- Map<String, List<MyPermissionInfo>> dangerousMap =
- new HashMap<String, List<MyPermissionInfo>>();
- Map<String, List<MyPermissionInfo> > normalMap =
- new HashMap<String, List<MyPermissionInfo>>();
- PermissionInfoComparator permComparator = new PermissionInfoComparator(mPm);
-
if (permList != null) {
// First pass to group permissions
for (MyPermissionInfo pInfo : permList) {
@@ -577,51 +594,26 @@ public class AppSecurityPermissions implements View.OnClickListener {
if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
continue;
}
- Map<String, List<MyPermissionInfo> > permInfoMap;
- if (pInfo.mNew) {
- permInfoMap = newMap;
- } else if ((pInfo.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE)
- == PermissionInfo.PROTECTION_DANGEROUS) {
- permInfoMap = dangerousMap;
- } else {
- permInfoMap = normalMap;
- }
- String grpName = (pInfo.group == null) ? mDefaultGrpName : pInfo.group;
- if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" belongs to group:"+grpName);
- List<MyPermissionInfo> grpPermsList = permInfoMap.get(grpName);
- if(grpPermsList == null) {
- grpPermsList = new ArrayList<MyPermissionInfo>();
- permInfoMap.put(grpName, grpPermsList);
- grpPermsList.add(pInfo);
- } else {
- int idx = Collections.binarySearch(grpPermsList, pInfo, permComparator);
- if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+grpPermsList.size());
- if (idx < 0) {
- idx = -idx-1;
- grpPermsList.add(idx, pInfo);
+ MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
+ if (group != null) {
+ pInfo.mLabel = pInfo.loadLabel(mPm);
+ addPermToList(group.mAllPermissions, pInfo);
+ if (pInfo.mNew) {
+ addPermToList(group.mNewPermissions, pInfo);
+ }
+ if ((group.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
+ addPermToList(group.mPersonalPermissions, pInfo);
+ } else {
+ addPermToList(group.mDevicePermissions, pInfo);
}
}
}
- // Second pass to actually form the descriptions
- // Look at dangerous permissions first
- aggregateGroupDescs(newMap, mNewMap, true);
- aggregateGroupDescs(dangerousMap, mDangerousMap, false);
- aggregateGroupDescs(normalMap, mNormalMap, false);
}
- mCurrentState = State.NO_PERMS;
- if (mNewMap.size() > 0 || mDangerousMap.size() > 0) {
- mCurrentState = (mNormalMap.size() > 0) ? State.BOTH : State.DANGEROUS_ONLY;
- } else if(mNormalMap.size() > 0) {
- mCurrentState = State.NORMAL_ONLY;
+ for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
+ pgrp.mLabel = pgrp.loadLabel(mPm);
+ mPermGroupsList.add(pgrp);
}
- if(localLOGV) Log.i(TAG, "mCurrentState=" + mCurrentState);
- showPermissions();
- }
-
- public void onClick(View v) {
- if(localLOGV) Log.i(TAG, "mExpanded="+mExpanded);
- mExpanded = !mExpanded;
- showPermissions();
+ Collections.sort(mPermGroupsList, mPermGroupComparator);
}
}
diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
index 1bd267f..9b8c5ae 100644
--- a/core/res/res/layout/app_permission_item.xml
+++ b/core/res/res/layout/app_permission_item.xml
@@ -19,37 +19,32 @@
Contains the group name and a list of permission labels under the group.
-->
-<RelativeLayout
+<view class="android.widget.AppSecurityPermissions$PermissionItemView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:background="?android:attr/selectableItemBackground">
<ImageView
android:id="@+id/perm_icon"
- android:layout_width="30dip"
- android:layout_height="30dip"
- android:layout_alignParentLeft="true"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="8dp"
android:scaleType="fitCenter" />
-
- <TextView
- android:id="@+id/permission_group"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textStyle="bold"
- android:paddingLeft="6dip"
- android:layout_toRightOf="@id/perm_icon"
+ <ImageView
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_height="match_parent"
+ android:background="?android:attr/dividerVertical" />
<TextView
- android:id="@+id/permission_list"
+ android:id="@+id/perm_name"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_marginTop="-4dip"
- android:paddingBottom="8dip"
- android:paddingLeft="6dip"
- android:layout_below="@id/permission_group"
- android:layout_toRightOf="@id/perm_icon"
+ android:layout_marginLeft="8dp"
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|left" />
-</RelativeLayout>
+</view>
diff --git a/core/res/res/layout/app_permission_item_old.xml b/core/res/res/layout/app_permission_item_old.xml
new file mode 100644
index 0000000..1bd267f
--- /dev/null
+++ b/core/res/res/layout/app_permission_item_old.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ Defines the layout of a single permission item.
+ Contains the group name and a list of permission labels under the group.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/perm_icon"
+ android:layout_width="30dip"
+ android:layout_height="30dip"
+ android:layout_alignParentLeft="true"
+ android:scaleType="fitCenter" />
+
+
+ <TextView
+ android:id="@+id/permission_group"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:paddingLeft="6dip"
+ android:layout_toRightOf="@id/perm_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/permission_list"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_marginTop="-4dip"
+ android:paddingBottom="8dip"
+ android:paddingLeft="6dip"
+ android:layout_below="@id/permission_group"
+ android:layout_toRightOf="@id/perm_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/core/res/res/layout/app_perms_summary.xml b/core/res/res/layout/app_perms_summary.xml
index 77dbc2e..509c502 100755
--- a/core/res/res/layout/app_perms_summary.xml
+++ b/core/res/res/layout/app_perms_summary.xml
@@ -26,88 +26,17 @@
android:id="@+id/no_permissions"
android:text="@string/no_permissions"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:paddingLeft="16dip"
- android:paddingRight="12dip"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
- <!-- List view containing list of new permissions categorized by groups. -->
+ <!-- Populated with all permissions. -->
<LinearLayout
- android:id="@+id/new_perms_list"
+ android:id="@+id/perms_list"
android:orientation="vertical"
android:layout_width="match_parent"
- android:paddingLeft="16dip"
- android:paddingRight="12dip"
- android:layout_height="wrap_content" />
-
- <!-- List view containing list of dangerous permissions categorized by groups. -->
- <LinearLayout
- android:id="@+id/dangerous_perms_list"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:paddingLeft="16dip"
- android:paddingRight="12dip"
- android:layout_height="wrap_content" />
-
- <!-- Clickable area letting user display additional permissions. -->
- <LinearLayout
- android:id="@+id/show_more"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layout_marginTop="12dip"
- android:layout_marginBottom="16dip">
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="16dip"
- android:paddingBottom="12dip"
- android:paddingLeft="16dip"
- android:duplicateParentState="true"
- android:background="?android:attr/selectableItemBackground">
-
- <TextView
- android:id="@+id/show_more_text"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:duplicateParentState="true"
- android:layout_alignTop="@+id/show_more_icon"
- android:layout_gravity="center_vertical"
- android:paddingLeft="36dip"
- android:layout_weight="1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <ImageView
- android:id="@id/show_more_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="12dip" />
-
- </LinearLayout>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- </LinearLayout>
-
- <!-- List view containing list of permissions that aren't dangerous. -->
- <LinearLayout
- android:id="@+id/non_dangerous_perms_list"
- android:orientation="vertical"
- android:paddingLeft="16dip"
- android:paddingRight="12dip"
- android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 978e2a8..2387e7a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -63,7 +63,6 @@
<java-symbol type="id" name="clearDefaultHint" />
<java-symbol type="id" name="contentPanel" />
<java-symbol type="id" name="customPanel" />
- <java-symbol type="id" name="dangerous_perms_list" />
<java-symbol type="id" name="datePicker" />
<java-symbol type="id" name="day" />
<java-symbol type="id" name="day_names" />
@@ -117,9 +116,7 @@
<java-symbol type="id" name="new_app_action" />
<java-symbol type="id" name="new_app_description" />
<java-symbol type="id" name="new_app_icon" />
- <java-symbol type="id" name="new_perms_list" />
<java-symbol type="id" name="no_permissions" />
- <java-symbol type="id" name="non_dangerous_perms_list" />
<java-symbol type="id" name="numberpicker_input" />
<java-symbol type="id" name="old_app_action" />
<java-symbol type="id" name="old_app_description" />
@@ -127,7 +124,9 @@
<java-symbol type="id" name="package_label" />
<java-symbol type="id" name="packages_list" />
<java-symbol type="id" name="pause" />
+ <java-symbol type="id" name="perms_list" />
<java-symbol type="id" name="perm_icon" />
+ <java-symbol type="id" name="perm_name" />
<java-symbol type="id" name="permission_group" />
<java-symbol type="id" name="permission_list" />
<java-symbol type="id" name="pickers" />
@@ -163,9 +162,6 @@
<java-symbol type="id" name="sha256_fingerprint" />
<java-symbol type="id" name="share" />
<java-symbol type="id" name="shortcut" />
- <java-symbol type="id" name="show_more" />
- <java-symbol type="id" name="show_more_icon" />
- <java-symbol type="id" name="show_more_text" />
<java-symbol type="id" name="skip_button" />
<java-symbol type="id" name="slider_group" />
<java-symbol type="id" name="split_action_bar" />
@@ -1044,6 +1040,7 @@
<java-symbol type="layout" name="alert_dialog_progress" />
<java-symbol type="layout" name="always_use_checkbox" />
<java-symbol type="layout" name="app_permission_item" />
+ <java-symbol type="layout" name="app_permission_item_old" />
<java-symbol type="layout" name="app_perms_summary" />
<java-symbol type="layout" name="calendar_view" />
<java-symbol type="layout" name="character_picker" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d779f72..3250507 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2981,7 +2981,7 @@
<!-- Do not translate. -->
<string name="permissions_format"><xliff:g id="perm_line1">%1$s</xliff:g>, <xliff:g id="perm_line2">%2$s</xliff:g></string>
<!-- Text that is placed at the front of a permission name that is being added to an app [CHAR LIMIT=NONE] -->
- <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ffffa3a3">NEW: </font></string>
+ <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff900000">NEW: </font></string>
<!-- Shown for an application when it doesn't require any permission grants. -->
<string name="no_permissions">No permissions required</string>
<!-- When installing an application, the less-dangerous permissions are hidden. If the user showed those, this is the text to hide them again. -->