summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSvet Ganov <svetoslavganov@google.com>2015-05-09 19:47:27 -0700
committerSvetoslav <svetoslavganov@google.com>2015-05-11 17:09:40 -0700
commit785a9b6369db4c46a389a43ae30e1f6e8003366b (patch)
treed1e3b969ebb7a71c7e7409148278493a690da6b6 /src
parenta8717e68410873ec51d3fa5fa805f3d3587fb743 (diff)
downloadandroid_packages_apps_PackageInstaller-785a9b6369db4c46a389a43ae30e1f6e8003366b.tar.gz
android_packages_apps_PackageInstaller-785a9b6369db4c46a389a43ae30e1f6e8003366b.tar.bz2
android_packages_apps_PackageInstaller-785a9b6369db4c46a389a43ae30e1f6e8003366b.zip
Add support for permissions gran/revoke policy - package installer.
Change-Id: Id2d5733db0978e909d7159b0eade2b85ec838924
Diffstat (limited to 'src')
-rw-r--r--src/com/android/packageinstaller/permission/model/AppPermissions.java24
-rw-r--r--src/com/android/packageinstaller/permission/model/Permission.java51
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionApps.java8
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionGroup.java173
-rw-r--r--src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java12
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java43
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java83
-rw-r--r--src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java1
8 files changed, 333 insertions, 62 deletions
diff --git a/src/com/android/packageinstaller/permission/model/AppPermissions.java b/src/com/android/packageinstaller/permission/model/AppPermissions.java
index 9480ce90..8258126a 100644
--- a/src/com/android/packageinstaller/permission/model/AppPermissions.java
+++ b/src/com/android/packageinstaller/permission/model/AppPermissions.java
@@ -18,6 +18,7 @@ package com.android.packageinstaller.permission.model;
import android.content.Context;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.util.ArrayMap;
import com.android.internal.util.ArrayUtils;
@@ -31,17 +32,21 @@ public final class AppPermissions {
private final Context mContext;
- private final PackageInfo mPackageInfo;
-
private final String[] mFilterPermissions;
private final CharSequence mAppLabel;
- public AppPermissions(Context context, PackageInfo packageInfo, String[] permissions) {
+ private final Runnable mOnErrorCallback;
+
+ private PackageInfo mPackageInfo;
+
+ public AppPermissions(Context context, PackageInfo packageInfo, String[] permissions,
+ Runnable onErrorCallback) {
mContext = context;
mPackageInfo = packageInfo;
mFilterPermissions = permissions;
mAppLabel = packageInfo.applicationInfo.loadLabel(context.getPackageManager());
+ mOnErrorCallback = onErrorCallback;
loadPermissionGroups();
}
@@ -50,6 +55,7 @@ public final class AppPermissions {
}
public void refresh() {
+ loadPackageInfo();
loadPermissionGroups();
}
@@ -65,6 +71,18 @@ public final class AppPermissions {
return new ArrayList<>(mGroups.values());
}
+
+ private void loadPackageInfo() {
+ try {
+ mPackageInfo = mContext.getPackageManager().getPackageInfo(
+ mPackageInfo.packageName, PackageManager.GET_PERMISSIONS);
+ } catch (PackageManager.NameNotFoundException e) {
+ if (mOnErrorCallback != null) {
+ mOnErrorCallback.run();
+ }
+ }
+ }
+
private void loadPermissionGroups() {
List<PermissionGroup> groups = new ArrayList<>();
diff --git a/src/com/android/packageinstaller/permission/model/Permission.java b/src/com/android/packageinstaller/permission/model/Permission.java
index 1f51fea9..bfe44af7 100644
--- a/src/com/android/packageinstaller/permission/model/Permission.java
+++ b/src/com/android/packageinstaller/permission/model/Permission.java
@@ -16,19 +16,24 @@
package com.android.packageinstaller.permission.model;
+import android.app.AppOpsManager;
+import android.content.pm.PackageManager;
+
public final class Permission {
private final String mName;
private final int mAppOp;
private boolean mGranted;
private boolean mAppOpAllowed;
+ private int mFlags;
public Permission(String name, boolean granted,
- int appOp, boolean appOpAllowed) {
+ int appOp, boolean appOpAllowed, int flags) {
mName = name;
mGranted = granted;
mAppOp = appOp;
mAppOpAllowed = appOpAllowed;
+ mFlags = flags;
}
public String getName() {
@@ -39,6 +44,10 @@ public final class Permission {
return mAppOp;
}
+ public boolean hasAppOp() {
+ return mAppOp != AppOpsManager.OP_NONE;
+ }
+
public boolean isGranted() {
return mGranted;
}
@@ -51,6 +60,46 @@ public final class Permission {
return mAppOpAllowed;
}
+ public boolean isUserFixed() {
+ return (mFlags & PackageManager.FLAG_PERMISSION_USER_FIXED) != 0;
+ }
+
+ public void setUserFixed(boolean userFixed) {
+ if (userFixed) {
+ mFlags |= PackageManager.FLAG_PERMISSION_USER_FIXED;
+ } else {
+ mFlags &= ~PackageManager.FLAG_PERMISSION_USER_FIXED;
+ }
+ }
+
+ public boolean isPolicyFixed() {
+ return (mFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
+ }
+
+ public boolean isUserSet() {
+ return (mFlags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
+ }
+
+ public void setUserSet(boolean userSet) {
+ if (userSet) {
+ mFlags |= PackageManager.FLAG_PERMISSION_USER_SET;
+ } else {
+ mFlags &= ~PackageManager.FLAG_PERMISSION_USER_SET;
+ }
+ }
+
+ public boolean shouldRevokeOnUpgrade() {
+ return (mFlags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0;
+ }
+
+ public void setRevokeOnUpgrade(boolean revokeOnUpgrade) {
+ if (revokeOnUpgrade) {
+ mFlags |= PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ } else {
+ mFlags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ }
+ }
+
public void setAppOpAllowed(boolean mAppOpAllowed) {
this.mAppOpAllowed = mAppOpAllowed;
}
diff --git a/src/com/android/packageinstaller/permission/model/PermissionApps.java b/src/com/android/packageinstaller/permission/model/PermissionApps.java
index 8f28433b..2ea2092d 100644
--- a/src/com/android/packageinstaller/permission/model/PermissionApps.java
+++ b/src/com/android/packageinstaller/permission/model/PermissionApps.java
@@ -130,11 +130,15 @@ public class PermissionApps {
}
public void grantRuntimePermissions() {
- mPermissionGroup.grantRuntimePermissions();
+ mPermissionGroup.grantRuntimePermissions(false);
}
public void revokeRuntimePermissions() {
- mPermissionGroup.revokeRuntimePermissions();
+ mPermissionGroup.revokeRuntimePermissions(false);
+ }
+
+ public boolean isPolicyFixed() {
+ return mPermissionGroup.isPolicyFixed();
}
@Override
diff --git a/src/com/android/packageinstaller/permission/model/PermissionGroup.java b/src/com/android/packageinstaller/permission/model/PermissionGroup.java
index 9a5291d8..749ac29e 100644
--- a/src/com/android/packageinstaller/permission/model/PermissionGroup.java
+++ b/src/com/android/packageinstaller/permission/model/PermissionGroup.java
@@ -37,6 +37,8 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
private static final String KILL_REASON_APP_OP_CHANGE = "Permission related app op changed";
private final Context mContext;
+ private final UserHandle mUserHandle;
+ private final PackageManager mPackageManager;
private final AppOpsManager mAppOps;
private final ActivityManager mActivityManager;
@@ -130,28 +132,24 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
continue;
}
-
final boolean granted = (packageInfo.requestedPermissionsFlags[i]
& PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
- final int appOp;
- final boolean appOpAllowed;
+ final int appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName)
+ ? AppOpsManager.permissionToOpCode(requestedPermissionInfo.name)
+ : AppOpsManager.OP_NONE;
- if (group.mAppSupportsRuntimePermissions) {
- appOp = AppOpsManager.OP_NONE;
- appOpAllowed = false;
- } else {
- appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName)
- ? AppOpsManager.permissionToOpCode(requestedPermissionInfo.name)
- : AppOpsManager.OP_NONE;
- appOpAllowed = appOp != AppOpsManager.OP_NONE
- && context.getSystemService(AppOpsManager.class).checkOp(appOp,
- packageInfo.applicationInfo.uid, packageInfo.packageName)
- == AppOpsManager.MODE_ALLOWED;
- }
+ final boolean appOpAllowed = appOp != AppOpsManager.OP_NONE
+ && context.getSystemService(AppOpsManager.class).checkOp(appOp,
+ packageInfo.applicationInfo.uid, packageInfo.packageName)
+ == AppOpsManager.MODE_ALLOWED;
+
+ final int flags = context.getPackageManager().getPermissionFlags(
+ requestedPermission, packageInfo.packageName,
+ new UserHandle(context.getUserId()));
Permission permission = new Permission(requestedPermission, granted,
- appOp, appOpAllowed);
+ appOp, appOpAllowed, flags);
group.addPermission(permission);
}
@@ -161,6 +159,8 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
private PermissionGroup(Context context, PackageInfo packageInfo, String name,
CharSequence label, String iconPkg, int iconResId) {
mContext = context;
+ mUserHandle = new UserHandle(mContext.getUserId());
+ mPackageManager = mContext.getPackageManager();
mPackageInfo = packageInfo;
mAppSupportsRuntimePermissions = packageInfo.applicationInfo
.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
@@ -212,7 +212,7 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
return true;
}
- public boolean grantRuntimePermissions() {
+ public boolean grantRuntimePermissions(boolean fixedByTheUser) {
final boolean isSharedUser = mPackageInfo.sharedUserId != null;
final int uid = mPackageInfo.applicationInfo.uid;
@@ -221,41 +221,76 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
// to the permission if the permission is granted to the app.
for (Permission permission : mPermissions.values()) {
if (mAppSupportsRuntimePermissions) {
+ // Grant the permission if needed.
if (!permission.isGranted()) {
- mContext.getPackageManager().grantPermission(mPackageInfo.packageName,
- permission.getName(), new UserHandle(mContext.getUserId()));
permission.setGranted(true);
+ mPackageManager.grantRuntimePermission(mPackageInfo.packageName,
+ permission.getName(), new UserHandle(mContext.getUserId()));
+ }
+
+ // Update the permission flags.
+ if (!fixedByTheUser) {
+ // Now the apps can ask for the permission as the user
+ // no longer has it fixed in a denied state.
+ if (permission.isUserFixed() || !permission.isUserSet()) {
+ permission.setUserFixed(false);
+ permission.setUserSet(true);
+ mPackageManager.updatePermissionFlags(permission.getName(),
+ mPackageInfo.packageName,
+ PackageManager.FLAG_PERMISSION_USER_FIXED
+ | PackageManager.FLAG_PERMISSION_USER_SET,
+ PackageManager.FLAG_PERMISSION_USER_SET,
+ mUserHandle);
+ }
+ }
+
+ // Enable the permission app op.
+ if (permission.hasAppOp() && !permission.isAppOpAllowed()) {
+ permission.setAppOpAllowed(true);
+ mAppOps.setMode(permission.getAppOp(), android.os.Process.myUid(),
+ mPackageInfo.packageName, AppOpsManager.MODE_ALLOWED);
}
} else {
// Legacy apps cannot have a not granted permission but just in case.
// Also if the permissions has no corresponding app op, then it is a
// third-party one and we do not offer toggling of such permissions.
- if (!permission.isGranted() || permission.getAppOp() == AppOpsManager.OP_NONE) {
+ if (!permission.isGranted() || !permission.hasAppOp()) {
continue;
}
if (!permission.isAppOpAllowed()) {
+ permission.setAppOpAllowed(true);
// It this is a shared user we want to enable the app op for all
// packages in the shared user to match the behavior of this
// shared user having a runtime permission.
if (isSharedUser) {
- String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+ // Enable the app op.
+ String[] packageNames = mPackageManager.getPackagesForUid(uid);
for (String packageName : packageNames) {
mAppOps.setMode(permission.getAppOp(), uid, packageName,
AppOpsManager.MODE_ALLOWED);
}
} else {
+ // Enable the app op.
mAppOps.setMode(permission.getAppOp(), uid, mPackageInfo.packageName,
AppOpsManager.MODE_ALLOWED);
}
+ // Mark that the permission should not be be granted on upgrade
+ // when the app begins supporting runtime permissions.
+ if (permission.shouldRevokeOnUpgrade()) {
+ permission.setRevokeOnUpgrade(false);
+ mPackageManager.updatePermissionFlags(permission.getName(),
+ mPackageInfo.packageName,
+ PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE,
+ 0, mUserHandle);
+ }
+
// Legacy apps do not know that they have to retry access to a
// resource due to changes in runtime permissions (app ops in this
// case). Therefore, we restart them on app op change, so they
// can pick up the change.
mActivityManager.killUid(uid, KILL_REASON_APP_OP_CHANGE);
-
- permission.setAppOpAllowed(true);
}
}
}
@@ -263,7 +298,7 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
return true;
}
- public boolean revokeRuntimePermissions() {
+ public boolean revokeRuntimePermissions(boolean fixedByTheUser) {
final boolean isSharedUser = mPackageInfo.sharedUserId != null;
final int uid = mPackageInfo.applicationInfo.uid;
@@ -272,40 +307,85 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
// to the permission if the permission is granted to the app.
for (Permission permission : mPermissions.values()) {
if (mAppSupportsRuntimePermissions) {
+ // Revoke the permission if needed.
if (permission.isGranted()) {
- mContext.getPackageManager().revokePermission(mPackageInfo.packageName,
- permission.getName(), new UserHandle(mContext.getUserId()));
permission.setGranted(false);
+ mPackageManager.revokeRuntimePermission(mPackageInfo.packageName,
+ permission.getName(), mUserHandle);
+ }
+
+ // Update the permission flags.
+ if (fixedByTheUser) {
+ // Take a note that the user fixed the permission.
+ if (permission.isUserSet() || !permission.isUserFixed()) {
+ permission.setUserSet(false);
+ permission.setUserFixed(true);
+ mPackageManager.updatePermissionFlags(permission.getName(),
+ mPackageInfo.packageName,
+ PackageManager.FLAG_PERMISSION_USER_SET
+ | PackageManager.FLAG_PERMISSION_USER_FIXED,
+ PackageManager.FLAG_PERMISSION_USER_FIXED,
+ mUserHandle);
+ }
+ } else {
+ if (!permission.isUserSet()) {
+ permission.setUserSet(true);
+ // Take a note that the user already chose once.
+ mPackageManager.updatePermissionFlags(permission.getName(),
+ mPackageInfo.packageName,
+ PackageManager.FLAG_PERMISSION_USER_SET,
+ PackageManager.FLAG_PERMISSION_USER_SET,
+ mUserHandle);
+ }
+ }
+
+ // Disable the permission app op.
+ if (permission.hasAppOp() && permission.isAppOpAllowed()) {
+ permission.setAppOpAllowed(false);
+ mAppOps.setMode(permission.getAppOp(), android.os.Process.myUid(),
+ mPackageInfo.packageName, AppOpsManager.MODE_IGNORED);
}
} else {
// Legacy apps cannot have a non-granted permission but just in case.
// Also if the permission has no corresponding app op, then it is a
// third-party one and we do not offer toggling of such permissions.
- if (!permission.isGranted() || permission.getAppOp() == AppOpsManager.OP_NONE) {
+ if (!permission.isGranted() || !permission.hasAppOp()) {
continue;
}
if (permission.isAppOpAllowed()) {
+ permission.setAppOpAllowed(false);
// It this is a shared user we want to enable the app op for all
// packages the the shared user to match the behavior of this
// shared user having a runtime permission.
if (isSharedUser) {
- String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+ String[] packageNames = mPackageManager.getPackagesForUid(uid);
for (String packageName : packageNames) {
+ // Disable the app op.
mAppOps.setMode(permission.getAppOp(), uid,
packageName, AppOpsManager.MODE_IGNORED);
}
} else {
+ // Disable the app op.
mAppOps.setMode(permission.getAppOp(), uid,
mPackageInfo.packageName, AppOpsManager.MODE_IGNORED);
}
+ // Mark that the permission should not be granted on upgrade
+ // when the app begins supporting runtime permissions.
+ if (!permission.shouldRevokeOnUpgrade()) {
+ permission.setRevokeOnUpgrade(true);
+ mPackageManager.updatePermissionFlags(permission.getName(),
+ mPackageInfo.packageName,
+ PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE,
+ PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE,
+ mUserHandle);
+ }
+
// Disabling an app op may put the app in a situation in which it
// has a handle to state it shouldn't have, so we have to kill the
// app. This matches the revoke runtime permission behavior.
mActivityManager.killUid(uid, KILL_REASON_APP_OP_CHANGE);
-
- permission.setAppOpAllowed(false);
}
}
}
@@ -317,6 +397,39 @@ public final class PermissionGroup implements Comparable<PermissionGroup> {
return new ArrayList<>(mPermissions.values());
}
+ public boolean isUserFixed() {
+ final int permissionCount = mPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ Permission permission = mPermissions.valueAt(i);
+ if (!permission.isUserFixed()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean isPolicyFixed() {
+ final int permissionCount = mPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ Permission permission = mPermissions.valueAt(i);
+ if (permission.isPolicyFixed()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isUserSet() {
+ final int permissionCount = mPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ Permission permission = mPermissions.valueAt(i);
+ if (!permission.isUserSet()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
@Override
public int compareTo(PermissionGroup another) {
final int result = mLabel.toString().compareTo(another.mLabel.toString());
diff --git a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java
index 6a87f9b0..cbe098a0 100644
--- a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java
@@ -146,7 +146,12 @@ public final class AppPermissionsFragment extends SettingsWithHeader
}
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(activity);
- mAppPermissions = new AppPermissions(activity, packageInfo, null);
+ mAppPermissions = new AppPermissions(activity, packageInfo, null, new Runnable() {
+ @Override
+ public void run() {
+ getActivity().finish();
+ }
+ });
for (PermissionGroup group : mAppPermissions.getPermissionGroups()) {
SwitchPreference preference = new SwitchPreference(activity);
@@ -156,6 +161,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader
group.getIconResId()));
preference.setTitle(group.getLabel());
preference.setPersistent(false);
+ preference.setEnabled(!group.isPolicyFixed());
screen.addPreference(preference);
}
@@ -172,9 +178,9 @@ public final class AppPermissionsFragment extends SettingsWithHeader
}
if (newValue == Boolean.TRUE) {
- group.grantRuntimePermissions();
+ group.grantRuntimePermissions(false);
} else {
- group.revokeRuntimePermissions();
+ group.revokeRuntimePermissions(false);
}
return true;
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
index dba459c2..66997c99 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
@@ -30,6 +30,8 @@ import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
@@ -42,6 +44,8 @@ public final class GrantPermissionViewHandler implements OnClickListener {
public static final String ARG_GROUP_INDEX = "ARG_GROUP_INDEX";
public static final String ARG_GROUP_ICON = "ARG_GROUP_ICON";
public static final String ARG_GROUP_MESSAGE = "ARG_GROUP_MESSAGE";
+ public static final String ARG_GROUP_SHOW_DO_NOT_ASK = "ARG_GROUP_SHOW_DO_NOT_ASK";
+ public static final String ARG_GROUP_DO_NOT_ASK_CHECKED = "ARG_GROUP_DO_NOT_ASK_CHECKED";
// Animation parameters.
private static final long SIZE_START_DELAY = 300;
@@ -60,10 +64,14 @@ public final class GrantPermissionViewHandler implements OnClickListener {
private int mGroupIndex;
private Icon mGroupIcon;
private CharSequence mGroupMessage;
+ private boolean mShowDonNotAsk;
+ private boolean mDoNotAskChecked;
private ImageView mIconView;
private TextView mCurrentGroupView;
private TextView mMessageView;
+ private CheckBox mDoNotAskCheckbox;
+ private Button mAllowButton;
private ViewHeightController mRootViewHeightController;
private ManualLayoutFrame mRootView;
@@ -83,7 +91,8 @@ public final class GrantPermissionViewHandler implements OnClickListener {
};
public interface OnRequestGrantPermissionGroupResult {
- public void onRequestGrantPermissionGroupResult(String name, boolean granted);
+ public void onRequestGrantPermissionGroupResult(String name, boolean granted,
+ boolean doNotAskAgain);
}
public GrantPermissionViewHandler(OnRequestGrantPermissionGroupResult resultListener,
@@ -98,6 +107,8 @@ public final class GrantPermissionViewHandler implements OnClickListener {
arguments.putInt(ARG_GROUP_INDEX, mGroupIndex);
arguments.putParcelable(ARG_GROUP_ICON, mGroupIcon);
arguments.putCharSequence(ARG_GROUP_MESSAGE, mGroupMessage);
+ arguments.putBoolean(ARG_GROUP_SHOW_DO_NOT_ASK, mShowDonNotAsk);
+ arguments.putBoolean(ARG_GROUP_DO_NOT_ASK_CHECKED, mDoNotAskCheckbox.isChecked());
}
public void loadSavedInstance(Bundle savedInstanceState) {
@@ -106,15 +117,19 @@ public final class GrantPermissionViewHandler implements OnClickListener {
mGroupIcon = savedInstanceState.getParcelable(ARG_GROUP_ICON);
mGroupCount = savedInstanceState.getInt(ARG_GROUP_COUNT);
mGroupIndex = savedInstanceState.getInt(ARG_GROUP_INDEX);
+ mShowDonNotAsk = savedInstanceState.getBoolean(ARG_GROUP_SHOW_DO_NOT_ASK);
+ mDoNotAskChecked = savedInstanceState.getBoolean(ARG_GROUP_DO_NOT_ASK_CHECKED);
}
public void showPermission(String groupName, int groupCount, int groupIndex, Icon icon,
- CharSequence message) {
+ CharSequence message, boolean showDonNotAsk) {
mGroupName = groupName;
mGroupCount = groupCount;
mGroupIndex = groupIndex;
mGroupIcon = icon;
mGroupMessage = message;
+ mShowDonNotAsk = showDonNotAsk;
+ mDoNotAskChecked = false;
// If this is a second (or later) permission and the views exist, then animate.
if (mIconView != null) {
if (mGroupIndex > 0) {
@@ -124,6 +139,8 @@ public final class GrantPermissionViewHandler implements OnClickListener {
updateGroup();
}
}
+
+ updateDoNotAskCheckBox();
}
private void animateToPermission() {
@@ -243,6 +260,8 @@ public final class GrantPermissionViewHandler implements OnClickListener {
mMessageView = (TextView) mRootView.findViewById(R.id.permission_message);
mIconView = (ImageView) mRootView.findViewById(R.id.permission_icon);
mCurrentGroupView = (TextView) mRootView.findViewById(R.id.current_page_text);
+ mDoNotAskCheckbox = (CheckBox) mRootView.findViewById(R.id.do_not_ask_checkbox);
+ mAllowButton = (Button) mRootView.findViewById(R.id.permission_allow_button);
mDescContainer = (ViewGroup) mRootView.findViewById(R.id.desc_container);
mCurrentDesc = (ViewGroup) mRootView.findViewById(R.id.perm_desc_root);
@@ -254,6 +273,7 @@ public final class GrantPermissionViewHandler implements OnClickListener {
if (mGroupName != null) {
updateDescription();
updateGroup();
+ updateDoNotAskCheckBox();
}
return mRootView;
@@ -274,19 +294,30 @@ public final class GrantPermissionViewHandler implements OnClickListener {
}
}
+ private void updateDoNotAskCheckBox() {
+ if (mShowDonNotAsk) {
+ mDoNotAskCheckbox.setVisibility(View.VISIBLE);
+ mDoNotAskCheckbox.setOnClickListener(this);
+ mDoNotAskCheckbox.setChecked(mDoNotAskChecked);
+ } else {
+ mDoNotAskCheckbox.setVisibility(View.GONE);
+ mDoNotAskCheckbox.setOnClickListener(null);
+ }
+ }
+
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.permission_allow_button:
- mResultListener.onRequestGrantPermissionGroupResult(mGroupName, true);
+ mResultListener.onRequestGrantPermissionGroupResult(mGroupName, true, false);
break;
case R.id.permission_deny_button:
- mResultListener.onRequestGrantPermissionGroupResult(mGroupName, false);
+ mResultListener.onRequestGrantPermissionGroupResult(mGroupName, false,
+ mDoNotAskCheckbox.isChecked());
break;
case R.id.do_not_ask_checkbox:
- //TODO: Implement me.
+ mAllowButton.setEnabled(!mDoNotAskCheckbox.isChecked());
break;
-
}
}
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
index 159a043f..9ed47df9 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
@@ -17,6 +17,7 @@
package com.android.packageinstaller.permission.ui;
import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -75,25 +76,54 @@ public class GrantPermissionsActivity extends Activity implements
}
PackageInfo callingPackageInfo = getCallingPackageInfo();
+
+ DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class);
+ final int permissionPolicy = devicePolicyManager.getPermissionPolicy(null);
+
+ // If calling package is null we default to deny all.
+ updateDefaultResults(callingPackageInfo, permissionPolicy);
+
if (callingPackageInfo == null) {
setResultAndFinish();
return;
}
- updateDefaultResults(callingPackageInfo);
-
- mAppPermissions = new AppPermissions(this, callingPackageInfo, mRequestedPermissions);
+ mAppPermissions = new AppPermissions(this, callingPackageInfo, mRequestedPermissions,
+ new Runnable() {
+ @Override
+ public void run() {
+ setResultAndFinish();
+ }
+ });
for (PermissionGroup group : mAppPermissions.getPermissionGroups()) {
- if (!group.areRuntimePermissionsGranted()) {
- mRequestGrantPermissionGroups.put(group.getName(), new GroupState(group));
+ // We allow the user to choose only non-fixed permissions. A permission
+ // is fixed either by device policy or the user denying with prejudice.
+ if (!group.areRuntimePermissionsGranted() &&
+ !(group.isUserFixed() || group.isPolicyFixed())) {
+
+ switch (permissionPolicy) {
+ case DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT: {
+ group.grantRuntimePermissions(false);
+ } break;
+
+ case DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY: {
+ group.revokeRuntimePermissions(false);
+ } break;
+
+ default: {
+ mRequestGrantPermissionGroups.put(
+ group.getName(), new GroupState(group));
+ } break;
+ }
}
}
- if (!showNextPermissionGroupFragment()) {
+ setContentView(mViewHandler.creatView());
+
+ if (!showNextPermissionGroupGrantRequest()) {
setResultAndFinish();
}
- setContentView(mViewHandler.creatView());
}
@Override
@@ -108,7 +138,7 @@ public class GrantPermissionsActivity extends Activity implements
mViewHandler.loadSavedInstance(savedInstanceState);
}
- private boolean showNextPermissionGroupFragment() {
+ private boolean showNextPermissionGroupGrantRequest() {
final int groupCount = mRequestGrantPermissionGroups.size();
for (int i = 0; i < groupCount; i++) {
@@ -139,7 +169,8 @@ public class GrantPermissionsActivity extends Activity implements
int icon = groupState.mGroup.getIconResId();
mViewHandler.showPermission(groupState.mGroup.getName(), groupCount, i,
- Icon.createWithResource(resources, icon), message);
+ Icon.createWithResource(resources, icon), message,
+ groupState.mGroup.isUserSet());
return true;
}
}
@@ -148,18 +179,20 @@ public class GrantPermissionsActivity extends Activity implements
}
@Override
- public void onRequestGrantPermissionGroupResult(String name, boolean granted) {
+ public void onRequestGrantPermissionGroupResult(String name, boolean granted,
+ boolean doNotAskAgain) {
GroupState groupState = mRequestGrantPermissionGroups.get(name);
if (groupState.mGroup != null) {
if (granted) {
- groupState.mGroup.grantRuntimePermissions();
+ groupState.mGroup.grantRuntimePermissions(doNotAskAgain);
groupState.mState = GroupState.STATE_ALLOWED;
updateGrantResults(groupState.mGroup);
} else {
+ groupState.mGroup.revokeRuntimePermissions(doNotAskAgain);
groupState.mState = GroupState.STATE_DENIED;
}
}
- if (!showNextPermissionGroupFragment()) {
+ if (!showNextPermissionGroupGrantRequest()) {
setResultAndFinish();
}
}
@@ -176,7 +209,8 @@ public class GrantPermissionsActivity extends Activity implements
}
}
- private int computePermissionGrantState(PackageInfo callingPackageInfo, String permission) {
+ private int computePermissionGrantState(PackageInfo callingPackageInfo,
+ String permission, int permissionPolicy) {
boolean permissionRequested = false;
for (int i = 0; i < callingPackageInfo.requestedPermissions.length; i++) {
@@ -201,10 +235,22 @@ public class GrantPermissionsActivity extends Activity implements
return PERMISSION_DENIED;
}
} catch (NameNotFoundException e) {
- /* ignore */
+ return PERMISSION_DENIED;
}
- return PERMISSION_DENIED_RUNTIME;
+ switch (permissionPolicy) {
+ case DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT: {
+ return PERMISSION_GRANTED;
+ }
+
+ case DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY: {
+ return PERMISSION_DENIED;
+ }
+
+ default: {
+ return PERMISSION_DENIED_RUNTIME;
+ }
+ }
}
private PackageInfo getCallingPackageInfo() {
@@ -217,11 +263,14 @@ public class GrantPermissionsActivity extends Activity implements
}
}
- private void updateDefaultResults(PackageInfo callingPackageInfo) {
+ private void updateDefaultResults(PackageInfo callingPackageInfo, int permissionPolicy) {
final int requestedPermCount = mRequestedPermissions.length;
for (int i = 0; i < requestedPermCount; i++) {
String permission = mRequestedPermissions[i];
- final int state = computePermissionGrantState(callingPackageInfo, permission);
+ final int state = callingPackageInfo != null
+ ? computePermissionGrantState(callingPackageInfo, permission,
+ permissionPolicy)
+ : PackageManager.PERMISSION_DENIED;
switch (state) {
case PERMISSION_GRANTED: {
mGrantResults[i] = PackageManager.PERMISSION_GRANTED;
diff --git a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java
index f5d7d711..85113842 100644
--- a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java
@@ -139,6 +139,7 @@ public final class PermissionAppsFragment extends SettingsWithHeader implements
pref.setIcon(app.getIcon());
pref.setTitle(app.getLabel());
pref.setPersistent(false);
+ pref.setEnabled(!app.isPolicyFixed());
preferences.addPreference(pref);
}
pref.setChecked(app.areRuntimePermissionsGranted());