diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java b/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java index 23afc1e91..13f297170 100644 --- a/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java +++ b/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java @@ -17,6 +17,7 @@ package org.fdroid.fdroid.privileged.views; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -60,14 +61,22 @@ import java.util.Set; * extended information consisting of all groups and permissions. * To use this view define a LinearLayout or any ViewGroup and add this * view by instantiating AppSecurityPermissions and invoking getPermissionsView. + *

+ * NOTES: + * Based on AOSP core/java/android/widget/AppSecurityPermissions + * latest included commit: a3f68ef2f6811cf72f1282214c0883db5a30901d + *

+ * To update this file: + * - Open https://github.com/android/platform_frameworks_base/commits/master/core/java/android/widget/AppSecurityPermissions.java + * - Start from latest included commit and include changes until the newest commit with care */ +@TargetApi(Build.VERSION_CODES.M) public class AppSecurityPermissions { private static final String TAG = "AppSecurityPermissions"; - 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 Context mContext; private final LayoutInflater mInflater; @@ -78,12 +87,12 @@ public class AppSecurityPermissions { private final PermissionInfoComparator mPermComparator = new PermissionInfoComparator(); private final CharSequence mNewPermPrefix; + // PermissionGroupInfo implements Parcelable but its Parcel constructor is private and thus cannot be extended. + @SuppressLint("ParcelCreator") static class MyPermissionGroupInfo extends PermissionGroupInfo { CharSequence mLabel; final List mNewPermissions = new ArrayList<>(); - final List mPersonalPermissions = new ArrayList<>(); - final List mDevicePermissions = new ArrayList<>(); final List mAllPermissions = new ArrayList<>(); MyPermissionGroupInfo(PermissionInfo perm) { @@ -95,17 +104,11 @@ public class AppSecurityPermissions { super(info); } - public Drawable loadGroupIcon(PackageManager pm) { + public Drawable loadGroupIcon(Context context, PackageManager pm) { if (icon != 0) { - return loadIcon(pm); + return (Build.VERSION.SDK_INT < 22) ? loadIcon(pm) : loadUnbadgedIcon(pm); } - try { - ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0); - return appInfo.loadIcon(pm); - } catch (NameNotFoundException e) { - // ignore - } - return null; + return context.getDrawable(R.drawable.ic_perm_device_info); } public int flags() { @@ -119,6 +122,8 @@ public class AppSecurityPermissions { } } + // PermissionInfo implements Parcelable but its Parcel constructor is private and thus cannot be extended. + @SuppressLint("ParcelCreator") private static class MyPermissionInfo extends PermissionInfo { CharSequence mLabel; @@ -159,7 +164,7 @@ public class AppSecurityPermissions { PackageManager pm = getContext().getPackageManager(); Drawable icon = null; if (first) { - icon = grp.loadGroupIcon(pm); + icon = grp.loadGroupIcon(getContext(), pm); } CharSequence label = perm.mLabel; if (perm.mNew && newPermPrefix != null) { @@ -203,7 +208,7 @@ public class AppSecurityPermissions { R.string.perms_description_app, appName) + "\n\n" + mPerm.name); } builder.setCancelable(true); - builder.setIcon(mGroup.loadGroupIcon(pm)); + builder.setIcon(mGroup.loadGroupIcon(getContext(), pm)); mDialog = builder.show(); mDialog.setCanceledOnTouchOutside(true); } @@ -240,14 +245,13 @@ public class AppSecurityPermissions { installedPkgInfo = mPm.getPackageInfo(info.packageName, PackageManager.GET_PERMISSIONS); } catch (NameNotFoundException e) { - // ignore + throw new RuntimeException("NameNotFoundException during GET_PERMISSIONS!"); } extractPerms(info, permSet, installedPkgInfo); } setPermissions(new ArrayList<>(permSet)); } - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private int[] getRequestedPermissionFlags(PackageInfo info) { if (Build.VERSION.SDK_INT < 16) { return new int[info.requestedPermissions.length]; @@ -255,23 +259,15 @@ public class AppSecurityPermissions { return info.requestedPermissionsFlags; } - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void extractPerms(PackageInfo info, Set permSet, - PackageInfo installedPkgInfo) { + PackageInfo installedPkgInfo) { final String[] strList = info.requestedPermissions; if (strList == null || strList.length == 0) { return; } - final int[] flagsList = getRequestedPermissionFlags(info); - for (int i = 0; i < strList.length; i++) { - String permName = strList[i]; - // If we are only looking at an existing app, then we only - // care about permissions that have actually been granted to it. - if (installedPkgInfo != null && info == installedPkgInfo && (flagsList[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) { - continue; - } + for (String permName : strList) { try { PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0); if (tmpPermInfo == null) { @@ -341,10 +337,6 @@ public class AppSecurityPermissions { switch (which) { case WHICH_NEW: return grp.mNewPermissions; - case WHICH_PERSONAL: - return grp.mPersonalPermissions; - case WHICH_DEVICE: - return grp.mDevicePermissions; default: return grp.mAllPermissions; } @@ -376,7 +368,7 @@ public class AppSecurityPermissions { * list of permission descriptions. */ private void displayPermissions(List groups, - LinearLayout permListView, int which) { + LinearLayout permListView, int which) { permListView.removeAllViews(); int spacing = (int) (8 * mContext.getResources().getDisplayMetrics().density); @@ -405,21 +397,28 @@ public class AppSecurityPermissions { } private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp, - MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) { + MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) { PermissionItemView permView = (PermissionItemView) mInflater.inflate( Build.VERSION.SDK_INT >= 17 && - (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0 - ? R.layout.app_permission_item_money : R.layout.app_permission_item, + (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0 + ? R.layout.app_permission_item_money : R.layout.app_permission_item, null); permView.setPermission(grp, perm, first, newPermPrefix); return permView; } - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private boolean isDisplayablePermission(PermissionInfo pInfo, int existingReqFlags) { final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; final boolean isNormal = base == PermissionInfo.PROTECTION_NORMAL; - final boolean isDangerous = base == PermissionInfo.PROTECTION_DANGEROUS; + + // TODO: do we want this in F-Droid? + // We do not show normal permissions in the UI. + //if (isNormal) { + // return false; + //} + + final boolean isDangerous = base == PermissionInfo.PROTECTION_DANGEROUS + || ((pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0); // Dangerous and normal permissions are always shown to the user if (isNormal || isDangerous) { @@ -439,16 +438,7 @@ public class AppSecurityPermissions { private final Collator sCollator = Collator.getInstance(); - PermissionGroupInfoComparator() { - } - 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; - } - if (a.priority() != b.priority()) { - return a.priority() > b.priority() ? -1 : 1; - } return sCollator.compare(a.mLabel, b.mLabel); } } @@ -466,7 +456,7 @@ public class AppSecurityPermissions { } private void addPermToList(List permList, - MyPermissionInfo pInfo) { + MyPermissionInfo pInfo) { if (pInfo.mLabel == null) { pInfo.mLabel = pInfo.loadLabel(mPm); } @@ -491,11 +481,6 @@ public class AppSecurityPermissions { if (pInfo.mNew) { addPermToList(group.mNewPermissions, pInfo); } - if ((group.flags() & PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) { - addPermToList(group.mPersonalPermissions, pInfo); - } else { - addPermToList(group.mDevicePermissions, pInfo); - } } } } diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java index a9af419b3..ceddb8f43 100644 --- a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java @@ -41,6 +41,11 @@ import android.widget.TextView; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.R; +/** + * NOTES: + * Parts are based on AOSP src/com/android/packageinstaller/PackageInstallerActivity.java + * latest included commit: c23d802958158d522e7350321ad9ac6d43013883 + */ public class InstallConfirmActivity extends Activity implements OnCancelListener, OnClickListener { public static final int RESULT_CANNOT_PARSE = RESULT_FIRST_USER + 1; @@ -107,9 +112,8 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener findViewById(R.id.tabscontainer).setVisibility(View.GONE); findViewById(R.id.divider).setVisibility(View.VISIBLE); } - final int np = perms.getPermissionCount(AppSecurityPermissions.WHICH_PERSONAL); - final int nd = perms.getPermissionCount(AppSecurityPermissions.WHICH_DEVICE); - if (np > 0 || nd > 0) { + final int n = perms.getPermissionCount(AppSecurityPermissions.WHICH_ALL); + if (n > 0) { permVisible = true; LayoutInflater inflater = (LayoutInflater) getSystemService( Context.LAYOUT_INFLATER_SERVICE); @@ -117,18 +121,8 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener if (mScrollView == null) { mScrollView = (CaffeinatedScrollView) root.findViewById(R.id.scrollview); } - final ViewGroup privacyList = (ViewGroup) root.findViewById(R.id.privacylist); - if (np > 0) { - privacyList.addView(perms.getPermissionsView(AppSecurityPermissions.WHICH_PERSONAL)); - } else { - privacyList.setVisibility(View.GONE); - } - final ViewGroup deviceList = (ViewGroup) root.findViewById(R.id.devicelist); - if (nd > 0) { - deviceList.addView(perms.getPermissionsView(AppSecurityPermissions.WHICH_DEVICE)); - } else { - root.findViewById(R.id.devicelist).setVisibility(View.GONE); - } + final ViewGroup permList = (ViewGroup) root.findViewById(R.id.permission_list); + permList.addView(perms.getPermissionsView(AppSecurityPermissions.WHICH_ALL)); adapter.addTab(tabHost.newTabSpec(TAB_ID_ALL).setIndicator( getText(R.string.allPerms)), root); } diff --git a/app/src/main/res/drawable/ic_perm_device_info.xml b/app/src/main/res/drawable/ic_perm_device_info.xml new file mode 100644 index 000000000..a0570f228 --- /dev/null +++ b/app/src/main/res/drawable/ic_perm_device_info.xml @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-v11/app_permission_item.xml b/app/src/main/res/layout-v11/app_permission_item.xml index 36aafd1fa..d7256a56e 100644 --- a/app/src/main/res/layout-v11/app_permission_item.xml +++ b/app/src/main/res/layout-v11/app_permission_item.xml @@ -33,7 +33,8 @@ android:layout_marginStart="16dp" android:layout_marginRight="8dp" android:layout_marginEnd="8dp" - android:scaleType="fitCenter" /> + android:scaleType="fitCenter" + android:tint="@android:color/black" /> + android:scaleType="fitCenter" + android:tint="@android:color/black" /> - - + - - - - - - - - + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingEnd="4dp" + android:paddingRight="4dp" + tools:ignore="RtlSymmetry" /> + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2b2cb2c8b..1d8062f77 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -361,8 +361,6 @@ be lost. It does not require any special access. New All - Privacy - Device Access This may cost you money Do you want to replace this app with the factory version? Do you want to uninstall this app?