Merge branch 'installer-ui-updates' into 'master'
Installer UI updates and lint fixes This updates UI classes of the installer to reflect the changes of AOSP's installer and fixes some lint errors. * No more differentiation between personal and device permissions (didn't even notice that there was a differentiation here...) * Icon for "other" permission group I carefully merged only the changes from AOSP that are related to us and decided against maintaining different versions of the AppSecurityPermissions. There will be more changes and discussions to the installer UI coming in the next days. See merge request !277
This commit is contained in:
commit
7e53baf4c1
@ -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.
|
||||
* <p/>
|
||||
* NOTES:
|
||||
* Based on AOSP core/java/android/widget/AppSecurityPermissions
|
||||
* latest included commit: a3f68ef2f6811cf72f1282214c0883db5a30901d
|
||||
* <p/>
|
||||
* 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<MyPermissionInfo> mNewPermissions = new ArrayList<>();
|
||||
final List<MyPermissionInfo> mPersonalPermissions = new ArrayList<>();
|
||||
final List<MyPermissionInfo> mDevicePermissions = new ArrayList<>();
|
||||
final List<MyPermissionInfo> 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<MyPermissionInfo> 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<MyPermissionGroupInfo> 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<MyPermissionInfo> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
21
app/src/main/res/drawable/ic_perm_device_info.xml
Normal file
21
app/src/main/res/drawable/ic_perm_device_info.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="48.0"
|
||||
android:viewportHeight="48.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M26.0,14.0l-4.0,0.0l0.0,4.0l4.0,0.0l0.0,-4.0zm0.0,8.0l-4.0,0.0l0.0,12.0l4.0,0.0L26.0,22.0zm8.0,-19.98L14.0,2.0c-2.21,0.0 -4.0,1.79 -4.0,4.0l0.0,36.0c0.0,2.21 1.79,4.0 4.0,4.0l20.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L38.0,6.0c0.0,-2.21 -1.79,-3.98 -4.0,-3.98zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0l0.0,28.0z"/>
|
||||
</vector>
|
@ -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" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -32,7 +32,8 @@
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:scaleType="fitCenter" />
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="@android:color/black" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2012 The Android Open Source Project
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2012 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.
|
||||
@ -17,37 +16,19 @@
|
||||
<!--
|
||||
This is the structure for the list of all permissions.
|
||||
-->
|
||||
<org.fdroid.fdroid.privileged.views.CaffeinatedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.fdroid.fdroid.privileged.views.CaffeinatedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/scrollview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/permission_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/privacylist"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp">
|
||||
<TextView
|
||||
style="?android:attr/listSeparatorTextViewStyle"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/privacyPerms" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:id="@+id/devicelist"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp">
|
||||
<TextView
|
||||
style="?android:attr/listSeparatorTextViewStyle"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/devicePerms" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingRight="4dp"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
</org.fdroid.fdroid.privileged.views.CaffeinatedScrollView>
|
@ -361,8 +361,6 @@
|
||||
be lost. It does not require any special access.</string>
|
||||
<string name="newPerms">New</string>
|
||||
<string name="allPerms">All</string>
|
||||
<string name="privacyPerms">Privacy</string>
|
||||
<string name="devicePerms">Device Access</string>
|
||||
<string name="perm_costs_money">This may cost you money</string>
|
||||
<string name="uninstall_update_confirm">Do you want to replace this app with the factory version?</string>
|
||||
<string name="uninstall_confirm">Do you want to uninstall this app?</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user