diff options
author | Svet Ganov <svetoslavganov@google.com> | 2015-05-09 19:47:27 -0700 |
---|---|---|
committer | Svetoslav <svetoslavganov@google.com> | 2015-05-11 17:09:40 -0700 |
commit | 785a9b6369db4c46a389a43ae30e1f6e8003366b (patch) | |
tree | d1e3b969ebb7a71c7e7409148278493a690da6b6 /src/com/android | |
parent | a8717e68410873ec51d3fa5fa805f3d3587fb743 (diff) | |
download | android_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/com/android')
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()); |