diff options
Diffstat (limited to 'src/com/android/packageinstaller/permission/ui/handheld')
9 files changed, 562 insertions, 209 deletions
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java index 0c249e55..36570a54 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java @@ -18,6 +18,7 @@ package com.android.packageinstaller.permission.ui.handheld; import android.app.ActionBar; import android.app.AlertDialog; +import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -28,20 +29,27 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceCategory; import android.preference.PreferenceGroup; import android.provider.Settings; +import android.util.IconDrawableFactory; import android.util.Log; import android.view.MenuItem; +import android.widget.Switch; + import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.model.AppPermissionGroup; +import com.android.packageinstaller.permission.model.Permission; +import com.android.packageinstaller.permission.utils.ArrayUtils; import com.android.packageinstaller.permission.utils.Utils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; public final class AllAppPermissionsFragment extends SettingsWithHeader { @@ -49,10 +57,20 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { private static final String KEY_OTHER = "other_perms"; + private static final String EXTRA_FILTER_GROUP = + "com.android.packageinstaller.extra.FILTER_GROUP"; + + private List<AppPermissionGroup> mGroups; + public static AllAppPermissionsFragment newInstance(String packageName) { + return newInstance(packageName, null); + } + + public static AllAppPermissionsFragment newInstance(String packageName, String filterGroup) { AllAppPermissionsFragment instance = new AllAppPermissionsFragment(); Bundle arguments = new Bundle(); arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); + arguments.putString(EXTRA_FILTER_GROUP, filterGroup); instance.setArguments(arguments); return instance; } @@ -63,7 +81,12 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { setHasOptionsMenu(true); final ActionBar ab = getActivity().getActionBar(); if (ab != null) { - ab.setTitle(R.string.all_permissions); + // If we target a group make this look like app permissions. + if (getArguments().getString(EXTRA_FILTER_GROUP) == null) { + ab.setTitle(R.string.all_permissions); + } else { + ab.setTitle(R.string.app_permissions); + } ab.setDisplayHomeAsUpEnabled(true); } } @@ -94,6 +117,7 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { ArrayList<Preference> prefs = new ArrayList<>(); // Used for sorting. prefs.add(otherGroup); String pkg = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); + String filterGroup = getArguments().getString(EXTRA_FILTER_GROUP); otherGroup.removeAll(); PackageManager pm = getContext().getPackageManager(); @@ -101,7 +125,8 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS); ApplicationInfo appInfo = info.applicationInfo; - final Drawable icon = appInfo.loadIcon(pm); + final Drawable icon = + IconDrawableFactory.newInstance(getContext()).getBadgedIcon(appInfo); final CharSequence label = appInfo.loadLabel(pm); Intent infoIntent = null; if (!getActivity().getIntent().getBooleanExtra( @@ -127,14 +152,41 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { continue; } - if (perm.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) { - PermissionGroupInfo group = getGroup(perm.group, pm); - PreferenceGroup pref = - findOrCreate(group != null ? group : perm, pm, prefs); - pref.addPreference(getPreference(perm, group, pm)); - } else if (perm.protectionLevel == PermissionInfo.PROTECTION_NORMAL) { - PermissionGroupInfo group = getGroup(perm.group, pm); - otherGroup.addPreference(getPreference(perm, group, pm)); + if (appInfo.isInstantApp() + && (perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) + == 0) { + continue; + } + if (appInfo.targetSdkVersion < Build.VERSION_CODES.M + && (perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) + != 0) { + continue; + } + + if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_DANGEROUS) { + PackageItemInfo group = getGroup(perm.group, pm); + if (group == null) { + group = perm; + } + // If we show a targeted group, then ignore everything else. + if (filterGroup != null && !group.name.equals(filterGroup)) { + continue; + } + PreferenceGroup pref = findOrCreate(group, pm, prefs); + pref.addPreference(getPreference(info, perm, group, pm)); + } else if (filterGroup == null) { + if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_NORMAL) { + PermissionGroupInfo group = getGroup(perm.group, pm); + otherGroup.addPreference(getPreference(info, + perm, group, pm)); + } + } + + // If we show a targeted group, then don't show 'other' permissions. + if (filterGroup != null) { + getPreferenceScreen().removePreference(otherGroup); } } } @@ -184,9 +236,19 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { return pref; } - private Preference getPreference(PermissionInfo perm, PermissionGroupInfo group, - PackageManager pm) { - Preference pref = new Preference(getContext()); + private Preference getPreference(PackageInfo packageInfo, PermissionInfo perm, + PackageItemInfo group, PackageManager pm) { + final Preference pref; + + // We allow individual permission control for some permissions if review enabled + final boolean mutable = Utils.isPermissionIndividuallyControlled(getContext(), perm.name); + if (mutable) { + pref = new MyMultiTargetSwitchPreference(getContext(), perm.name, + getPermissionGroup(packageInfo, perm.name)); + } else { + pref = new Preference(getContext()); + } + Drawable icon = null; if (perm.icon != 0) { icon = perm.loadIcon(pm); @@ -198,17 +260,97 @@ public final class AllAppPermissionsFragment extends SettingsWithHeader { pref.setIcon(Utils.applyTint(getContext(), icon, android.R.attr.colorControlNormal)); pref.setTitle(perm.loadLabel(pm)); final CharSequence desc = perm.loadDescription(pm); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - new AlertDialog.Builder(getContext()) - .setMessage(desc) - .setPositiveButton(android.R.string.ok, null) - .show(); - return true; - } + + pref.setOnPreferenceClickListener((Preference preference) -> { + new AlertDialog.Builder(getContext()) + .setMessage(desc) + .setPositiveButton(android.R.string.ok, null) + .show(); + return mutable; }); return pref; } -}
\ No newline at end of file + + private AppPermissionGroup getPermissionGroup(PackageInfo packageInfo, + String permission) { + AppPermissionGroup appPermissionGroup = null; + if (mGroups != null) { + final int groupCount = mGroups.size(); + for (int i = 0; i < groupCount; i++) { + AppPermissionGroup currentPermissionGroup = mGroups.get(i); + if (currentPermissionGroup.hasPermission(permission)) { + appPermissionGroup = currentPermissionGroup; + break; + } + } + } + if (appPermissionGroup == null) { + appPermissionGroup = AppPermissionGroup.create( + getContext(), packageInfo, permission); + if (mGroups == null) { + mGroups = new ArrayList<>(); + } + mGroups.add(appPermissionGroup); + } + return appPermissionGroup; + } + + private static final class MyMultiTargetSwitchPreference extends MultiTargetSwitchPreference { + MyMultiTargetSwitchPreference(Context context, String permission, + AppPermissionGroup appPermissionGroup) { + super(context); + + setChecked(appPermissionGroup.areRuntimePermissionsGranted( + new String[] {permission})); + + setSwitchOnClickListener(v -> { + Switch switchView = (Switch) v; + if (switchView.isChecked()) { + appPermissionGroup.grantRuntimePermissions(false, + new String[]{permission}); + // We are granting a permission from a group but since this is an + // individual permission control other permissions in the group may + // be revoked, hence we need to mark them user fixed to prevent the + // app from requesting a non-granted permission and it being granted + // because another permission in the group is granted. This applies + // only to apps that support runtime permissions. + if (appPermissionGroup.doesSupportRuntimePermissions()) { + int grantedCount = 0; + String[] revokedPermissionsToFix = null; + final int permissionCount = appPermissionGroup.getPermissions().size(); + for (int i = 0; i < permissionCount; i++) { + Permission current = appPermissionGroup.getPermissions().get(i); + if (!current.isGranted()) { + if (!current.isUserFixed()) { + revokedPermissionsToFix = ArrayUtils.appendString( + revokedPermissionsToFix, current.getName()); + } + } else { + grantedCount++; + } + } + if (revokedPermissionsToFix != null) { + // If some permissions were not granted then they should be fixed. + appPermissionGroup.revokeRuntimePermissions(true, + revokedPermissionsToFix); + } else if (appPermissionGroup.getPermissions().size() == grantedCount) { + // If all permissions are granted then they should not be fixed. + appPermissionGroup.grantRuntimePermissions(false); + } + } + } else { + appPermissionGroup.revokeRuntimePermissions(true, + new String[]{permission}); + // If we just revoked the last permission we need to clear + // the user fixed state as now the app should be able to + // request them at runtime if supported. + if (appPermissionGroup.doesSupportRuntimePermissions() + && !appPermissionGroup.areRuntimePermissionsGranted()) { + appPermissionGroup.revokeRuntimePermissions(false); + } + } + }); + } + } +} diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java index c824325c..89869976 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java @@ -16,13 +16,14 @@ package com.android.packageinstaller.permission.ui.handheld; +import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; + import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -36,18 +37,19 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import android.provider.Settings; +import android.util.IconDrawableFactory; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; +import android.widget.Switch; import android.widget.Toast; + import com.android.packageinstaller.R; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.AppPermissions; +import com.android.packageinstaller.permission.model.Permission; import com.android.packageinstaller.permission.utils.LocationUtils; import com.android.packageinstaller.permission.utils.SafetyNetLogger; import com.android.packageinstaller.permission.utils.Utils; @@ -57,8 +59,6 @@ import com.android.settingslib.RestrictedLockUtils; import java.util.ArrayList; import java.util.List; -import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; - public final class AppPermissionsFragment extends SettingsWithHeader implements OnPreferenceChangeListener { @@ -130,12 +130,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader } case MENU_ALL_PERMS: { - Fragment frag = AllAppPermissionsFragment.newInstance( - getArguments().getString(Intent.EXTRA_PACKAGE_NAME)); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("AllPerms") - .commit(); + showAllPermissions(null); return true; } } @@ -158,6 +153,16 @@ public final class AppPermissionsFragment extends SettingsWithHeader getClass().getName()); } + private void showAllPermissions(String filterGroup) { + Fragment frag = AllAppPermissionsFragment.newInstance( + getArguments().getString(Intent.EXTRA_PACKAGE_NAME), + filterGroup); + getFragmentManager().beginTransaction() + .replace(android.R.id.content, frag) + .addToBackStack("AllPerms") + .commit(); + } + private static void bindUi(SettingsWithHeader fragment, PackageInfo packageInfo) { Activity activity = fragment.getActivity(); PackageManager pm = activity.getPackageManager(); @@ -168,7 +173,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader .setData(Uri.fromParts("package", packageInfo.packageName, null)); } - Drawable icon = appInfo.loadIcon(pm); + Drawable icon = IconDrawableFactory.newInstance(activity).getBadgedIcon(appInfo); CharSequence label = appInfo.loadLabel(pm); fragment.setHeader(icon, label, infoIntent); @@ -208,13 +213,36 @@ public final class AppPermissionsFragment extends SettingsWithHeader boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG); RestrictedSwitchPreference preference = new RestrictedSwitchPreference(context); - preference.setOnPreferenceChangeListener(this); + preference.setChecked(group.areRuntimePermissionsGranted()); + + // Some groups may be a double target - one to toggle and one to fine manage + if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) { + preference.setOnPreferenceClickListener((pref) -> { + showAllPermissions(group.getName()); + return false; + }); + + preference.setSwitchOnClickListener(v -> { + Switch switchView = (Switch) v; + onPreferenceChange(preference, switchView.isChecked()); + updateSummaryForIndividuallyControlledPermissionGroup( + group, preference); + preference.setCheckedOverride(switchView.isChecked()); + }); + + updateSummaryForIndividuallyControlledPermissionGroup(group, preference); + } else { + preference.setOnPreferenceChangeListener(this); + } + preference.setKey(group.getName()); Drawable icon = Utils.loadDrawable(context.getPackageManager(), group.getIconPkg(), group.getIconResId()); preference.setIcon(Utils.applyTint(getContext(), icon, android.R.attr.colorControlNormal)); preference.setTitle(group.getLabel()); + + if (group.isPolicyFixed()) { EnforcedAdmin admin = RestrictedLockUtils.getProfileOrDeviceOwner(getContext(), group.getUserId()); @@ -227,7 +255,6 @@ public final class AppPermissionsFragment extends SettingsWithHeader } } preference.setPersistent(false); - preference.setChecked(group.areRuntimePermissionsGranted()); if (isPlatform) { screen.addPreference(preference); @@ -286,16 +313,22 @@ public final class AppPermissionsFragment extends SettingsWithHeader new AlertDialog.Builder(getContext()) .setMessage(grantedByDefault ? R.string.system_warning : R.string.old_sdk_deny_warning) - .setNegativeButton(R.string.cancel, null) + .setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> { + if (preference instanceof MultiTargetSwitchPreference) { + ((MultiTargetSwitchPreference) preference).setCheckedOverride(true); + } + }) .setPositiveButton(R.string.grant_dialog_button_deny_anyway, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ((SwitchPreference) preference).setChecked(false); - group.revokeRuntimePermissions(false); - if (!grantedByDefault) { - mHasConfirmedRevoke = true; - } + (DialogInterface dialog, int which) -> { + ((SwitchPreference) preference).setChecked(false); + group.revokeRuntimePermissions(false); + if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), + group.getName())) { + updateSummaryForIndividuallyControlledPermissionGroup( + group, preference); + } + if (!grantedByDefault) { + mHasConfirmedRevoke = true; } }) .show(); @@ -314,6 +347,32 @@ public final class AppPermissionsFragment extends SettingsWithHeader logToggledGroups(); } + private void updateSummaryForIndividuallyControlledPermissionGroup( + AppPermissionGroup group, Preference preference) { + int revokedCount = 0; + List<Permission> permissions = group.getPermissions(); + final int permissionCount = permissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = permissions.get(i); + if (group.doesSupportRuntimePermissions() + ? !permission.isGranted() : !permission.isAppOpAllowed()) { + revokedCount++; + } + } + + final int resId; + if (revokedCount == 0) { + resId = R.string.permission_revoked_none; + } else if (revokedCount == permissionCount) { + resId = R.string.permission_revoked_all; + } else { + resId = R.string.permission_revoked_count; + } + + String summary = getString(resId, revokedCount); + preference.setSummary(summary); + } + private void addToggledGroup(AppPermissionGroup group) { if (mToggledGroups == null) { mToggledGroups = new ArrayList<>(); diff --git a/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java b/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java index 6342826f..eec43b76 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java @@ -16,7 +16,8 @@ package com.android.packageinstaller.permission.ui.handheld; -import android.content.Context; +import android.app.Activity; +import android.content.Intent; import android.graphics.drawable.Icon; import android.os.Bundle; import android.view.LayoutInflater; @@ -34,10 +35,11 @@ import android.widget.TextView; import com.android.packageinstaller.R; import com.android.packageinstaller.permission.ui.ButtonBarLayout; import com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler; +import com.android.packageinstaller.permission.ui.ManagePermissionsActivity; import com.android.packageinstaller.permission.ui.ManualLayoutFrame; -public final class GrantPermissionsViewHandlerImpl - implements GrantPermissionsViewHandler, OnClickListener { +public class GrantPermissionsViewHandlerImpl implements GrantPermissionsViewHandler, + OnClickListener { public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME"; public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT"; @@ -51,7 +53,9 @@ public final class GrantPermissionsViewHandlerImpl private static final long OUT_DURATION = 200; private static final long IN_DURATION = 300; - private final Context mContext; + private final Activity mActivity; + private final String mAppPackageName; + private final boolean mPermissionReviewRequired; private ResultListener mResultListener; @@ -68,6 +72,7 @@ public final class GrantPermissionsViewHandlerImpl private TextView mMessageView; private CheckBox mDoNotAskCheckbox; private Button mAllowButton; + private Button mMoreInfoButton; private ManualLayoutFrame mRootView; @@ -77,8 +82,10 @@ public final class GrantPermissionsViewHandlerImpl private ViewGroup mDialogContainer; private ButtonBarLayout mButtonBar; - public GrantPermissionsViewHandlerImpl(Context context) { - mContext = context; + public GrantPermissionsViewHandlerImpl(Activity activity, String appPackageName) { + mActivity = activity; + mAppPackageName = appPackageName; + mPermissionReviewRequired = activity.getPackageManager().isPermissionReviewModeEnabled(); } @Override @@ -140,7 +147,7 @@ public final class GrantPermissionsViewHandlerImpl private void animateOldContent(Runnable callback) { // Fade out old description group and scale out the icon for it. - Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, + Interpolator interpolator = AnimationUtils.loadInterpolator(mActivity, android.R.interpolator.fast_out_linear_in); // Icon scale to zero @@ -170,7 +177,7 @@ public final class GrantPermissionsViewHandlerImpl } private void attachNewContent(final Runnable callback) { - mCurrentDesc = (ViewGroup) LayoutInflater.from(mContext).inflate( + mCurrentDesc = (ViewGroup) LayoutInflater.from(mActivity).inflate( R.layout.permission_description, mDescContainer, false); mDescContainer.removeAllViews(); mDescContainer.addView(mCurrentDesc); @@ -200,7 +207,7 @@ public final class GrantPermissionsViewHandlerImpl mDescContainer.animate() .translationY(0) .scaleY(1.0f) - .setInterpolator(AnimationUtils.loadInterpolator(mContext, + .setInterpolator(AnimationUtils.loadInterpolator(mActivity, android.R.interpolator.linear_out_slow_in)) .setDuration(IN_DURATION) .withEndAction(callback) @@ -224,7 +231,7 @@ public final class GrantPermissionsViewHandlerImpl } private void animateNewContent() { - Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, + Interpolator interpolator = AnimationUtils.loadInterpolator(mActivity, android.R.interpolator.linear_out_slow_in); // Description slide in @@ -265,7 +272,7 @@ public final class GrantPermissionsViewHandlerImpl @Override public View createView() { - mRootView = (ManualLayoutFrame) LayoutInflater.from(mContext) + mRootView = (ManualLayoutFrame) LayoutInflater.from(mActivity) .inflate(R.layout.grant_permissions, null); mButtonBar = (ButtonBarLayout) mRootView.findViewById(R.id.button_group); mButtonBar.setAllowStacking(true); @@ -273,13 +280,20 @@ public final class GrantPermissionsViewHandlerImpl 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); + mAllowButton.setOnClickListener(this); + + if (mPermissionReviewRequired) { + mMoreInfoButton = (Button) mRootView.findViewById(R.id.permission_more_info_button); + mMoreInfoButton.setVisibility(View.VISIBLE); + mMoreInfoButton.setOnClickListener(this); + } mDialogContainer = (ViewGroup) mRootView.findViewById(R.id.dialog_container); mDescContainer = (ViewGroup) mRootView.findViewById(R.id.desc_container); mCurrentDesc = (ViewGroup) mRootView.findViewById(R.id.perm_desc_root); - mAllowButton.setOnClickListener(this); mRootView.findViewById(R.id.permission_deny_button).setOnClickListener(this); mDoNotAskCheckbox.setOnClickListener(this); @@ -298,17 +312,17 @@ public final class GrantPermissionsViewHandlerImpl } private void updateDescription() { - mIconView.setImageDrawable(mGroupIcon.loadDrawable(mContext)); + mIconView.setImageDrawable(mGroupIcon.loadDrawable(mActivity)); mMessageView.setText(mGroupMessage); } private void updateGroup() { if (mGroupCount > 1) { mCurrentGroupView.setVisibility(View.VISIBLE); - mCurrentGroupView.setText(mContext.getString(R.string.current_permission_template, + mCurrentGroupView.setText(mActivity.getString(R.string.current_permission_template, mGroupIndex + 1, mGroupCount)); } else { - mCurrentGroupView.setVisibility(View.INVISIBLE); + mCurrentGroupView.setVisibility(View.GONE); } } @@ -340,6 +354,12 @@ public final class GrantPermissionsViewHandlerImpl mShowDonNotAsk && mDoNotAskCheckbox.isChecked()); } break; + case R.id.permission_more_info_button: + Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppPackageName); + intent.putExtra(ManagePermissionsActivity.EXTRA_ALL_PERMISSIONS, true); + mActivity.startActivity(intent); + break; case R.id.do_not_ask_checkbox: mAllowButton.setEnabled(!mDoNotAskCheckbox.isChecked()); break; diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java new file mode 100644 index 00000000..4f740e2c --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.packageinstaller.permission.ui.handheld; + +import android.view.MenuItem; + +/** + * Fragment that allows the user to manage custom permissions. + */ +public class ManageCustomPermissionsFragment extends ManagePermissionsFragment { + @Override + public void onStart() { + super.onStart(); + + getActivity().setTitle(com.android.packageinstaller.R.string.additional_permissions); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + getFragmentManager().popBackStack(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void updatePermissionsUi() { + updatePermissionsUi(false); + } +} diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java index 238af36d..e50a1d89 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java @@ -16,23 +16,16 @@ package com.android.packageinstaller.permission.ui.handheld; import android.app.ActionBar; -import android.app.FragmentTransaction; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceScreen; import android.util.ArraySet; import android.util.Log; -import android.view.MenuItem; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; + import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.PermissionApps; import com.android.packageinstaller.permission.model.PermissionApps.PmCache; import com.android.packageinstaller.permission.model.PermissionGroup; import com.android.packageinstaller.permission.model.PermissionGroups; @@ -40,25 +33,20 @@ import com.android.packageinstaller.permission.utils.Utils; import java.util.List; -public final class ManagePermissionsFragment extends PermissionsFrameFragment +/** + * Superclass for fragments allowing the user to manage permissions. + */ +abstract class ManagePermissionsFragment extends PermissionsFrameFragment implements PermissionGroups.PermissionsGroupsChangeCallback, Preference.OnPreferenceClickListener { private static final String LOG_TAG = "ManagePermissionsFragment"; - private static final String OS_PKG = "android"; - - private static final String EXTRA_PREFS_KEY = "extra_prefs_key"; + static final String OS_PKG = "android"; private ArraySet<String> mLauncherPkgs; private PermissionGroups mPermissions; - private PreferenceScreen mExtraScreen; - - public static ManagePermissionsFragment newInstance() { - return new ManagePermissionsFragment(); - } - @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -69,23 +57,7 @@ public final class ManagePermissionsFragment extends PermissionsFrameFragment ab.setDisplayHomeAsUpEnabled(true); } mLauncherPkgs = Utils.getLauncherPackages(getContext()); - mPermissions = new PermissionGroups(getActivity(), getLoaderManager(), this); - } - - @Override - public void onResume() { - super.onResume(); - mPermissions.refresh(); - updatePermissionsUi(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getActivity().finish(); - return true; - } - return super.onOptionsItemSelected(item); + mPermissions = new PermissionGroups(getContext(), getLoaderManager(), this); } @Override @@ -108,27 +80,34 @@ public final class ManagePermissionsFragment extends PermissionsFrameFragment return true; } - @Override - public void onPermissionGroupsChanged() { - updatePermissionsUi(); + /** + * @return the permissions + */ + protected PermissionGroups getPermissions() { + return mPermissions; } @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindPermissionUi(getActivity(), getView()); - } - - private static void bindPermissionUi(Context context, View rootView) { - if (context == null || rootView == null) { - return; - } + public void onPermissionGroupsChanged() { + updatePermissionsUi(); } - private void updatePermissionsUi() { + /** + * Update the preferences to show the new {@link #getPermissions() permissions}. + */ + protected abstract void updatePermissionsUi(); + + /** + * Add preferences for all permissions of a type to the preference screen. + * + * @param addSystemPermissions If the permissions added should be system permissions or not + * + * @return The preference screen the permissions were added to + */ + protected PreferenceScreen updatePermissionsUi(boolean addSystemPermissions) { Context context = getActivity(); if (context == null) { - return; + return null; } List<PermissionGroup> groups = mPermissions.getGroups(); @@ -136,6 +115,8 @@ public final class ManagePermissionsFragment extends PermissionsFrameFragment if (screen == null) { screen = getPreferenceManager().createPreferenceScreen(getActivity()); setPreferenceScreen(screen); + } else { + screen.removeAll(); } // Use this to speed up getting the info for all of the PermissionApps below. @@ -144,107 +125,30 @@ public final class ManagePermissionsFragment extends PermissionsFrameFragment for (PermissionGroup group : groups) { boolean isSystemPermission = group.getDeclaringPackage().equals(OS_PKG); - Preference preference = findPreference(group.getName()); - if (preference == null && mExtraScreen != null) { - preference = mExtraScreen.findPreference(group.getName()); - } - if (preference == null) { - preference = new Preference(context); - preference.setOnPreferenceClickListener(this); - preference.setKey(group.getName()); - preference.setIcon(Utils.applyTint(context, group.getIcon(), - android.R.attr.colorControlNormal)); - preference.setTitle(group.getLabel()); - // Set blank summary so that no resizing/jumping happens when the summary is loaded. - preference.setSummary(" "); - preference.setPersistent(false); - if (isSystemPermission) { + if (addSystemPermissions == isSystemPermission) { + Preference preference = findPreference(group.getName()); + + if (preference == null) { + preference = new Preference(context); + preference.setOnPreferenceClickListener(this); + preference.setKey(group.getName()); + preference.setIcon(Utils.applyTint(context, group.getIcon(), + android.R.attr.colorControlNormal)); + preference.setTitle(group.getLabel()); + // Set blank summary so that no resizing/jumping happens when the summary is + // loaded. + preference.setSummary(" "); + preference.setPersistent(false); screen.addPreference(preference); - } else { - if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(context); - } - mExtraScreen.addPreference(preference); } + preference.setSummary(getString(R.string.app_permissions_group_summary, + group.getGranted(), group.getTotal())); } - final Preference finalPref = preference; - - new PermissionApps(getContext(), group.getName(), new PermissionApps.Callback() { - @Override - public void onPermissionsLoaded(PermissionApps permissionApps) { - if (getActivity() == null) { - return; - } - int granted = permissionApps.getGrantedCount(mLauncherPkgs); - int total = permissionApps.getTotalCount(mLauncherPkgs); - finalPref.setSummary(getString(R.string.app_permissions_group_summary, - granted, total)); - } - }, cache).refresh(false); - } - - if (mExtraScreen != null && mExtraScreen.getPreferenceCount() > 0 - && screen.findPreference(EXTRA_PREFS_KEY) == null) { - Preference extraScreenPreference = new Preference(context); - extraScreenPreference.setKey(EXTRA_PREFS_KEY); - extraScreenPreference.setIcon(Utils.applyTint(context, - R.drawable.ic_more_items, - android.R.attr.colorControlNormal)); - extraScreenPreference.setTitle(R.string.additional_permissions); - extraScreenPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - AdditionalPermissionsFragment frag = new AdditionalPermissionsFragment(); - frag.setTargetFragment(ManagePermissionsFragment.this, 0); - FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(android.R.id.content, frag); - ft.addToBackStack(null); - ft.commit(); - return true; - } - }); - int count = mExtraScreen.getPreferenceCount(); - extraScreenPreference.setSummary(getResources().getQuantityString( - R.plurals.additional_permissions_more, count, count)); - screen.addPreference(extraScreenPreference); } if (screen.getPreferenceCount() != 0) { setLoading(false /* loading */, true /* animate */); } - } - - public static class AdditionalPermissionsFragment extends PermissionsFrameFragment { - @Override - public void onCreate(Bundle icicle) { - setLoading(true /* loading */, false /* animate */); - super.onCreate(icicle); - getActivity().setTitle(R.string.additional_permissions); - setHasOptionsMenu(true); - setPreferenceScreen(((ManagePermissionsFragment) getTargetFragment()).mExtraScreen); - setLoading(false /* loading */, true /* animate */); - } - - @Override - public void onDestroy() { - getActivity().setTitle(R.string.app_permissions); - super.onDestroy(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getFragmentManager().popBackStack(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindPermissionUi(getActivity(), getView()); - } + return screen; } } diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java new file mode 100644 index 00000000..075ab3ce --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2016 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. + */ +package com.android.packageinstaller.permission.ui.handheld; + +import android.app.FragmentTransaction; +import android.preference.Preference; +import android.preference.PreferenceScreen; +import android.view.MenuItem; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.model.PermissionGroup; +import com.android.packageinstaller.permission.utils.Utils; + +import java.util.List; + +/** + * Fragment that allows the user to manage standard permissions. + */ +public final class ManageStandardPermissionsFragment extends ManagePermissionsFragment { + private static final String EXTRA_PREFS_KEY = "extra_prefs_key"; + + /** + * @return A new fragment + */ + public static ManageStandardPermissionsFragment newInstance() { + return new ManageStandardPermissionsFragment(); + } + + @Override + public void onStart() { + super.onStart(); + + getActivity().setTitle(com.android.packageinstaller.R.string.app_permissions); + } + + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + getActivity().finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void updatePermissionsUi() { + PreferenceScreen screen = updatePermissionsUi(true); + if (screen == null) { + return; + } + + // Check if we need an additional permissions preference + List<PermissionGroup> groups = getPermissions().getGroups(); + int numExtraPermissions = 0; + for (PermissionGroup group : groups) { + if (!group.getDeclaringPackage().equals(ManagePermissionsFragment.OS_PKG)) { + numExtraPermissions++; + } + } + + Preference additionalPermissionsPreference = screen.findPreference(EXTRA_PREFS_KEY); + if (numExtraPermissions == 0) { + if (additionalPermissionsPreference != null) { + screen.removePreference(additionalPermissionsPreference); + } + } else { + if (additionalPermissionsPreference == null) { + additionalPermissionsPreference = new Preference(getActivity()); + additionalPermissionsPreference.setKey(EXTRA_PREFS_KEY); + additionalPermissionsPreference.setIcon(Utils.applyTint(getActivity(), + R.drawable.ic_more_items, + android.R.attr.colorControlNormal)); + additionalPermissionsPreference.setTitle(R.string.additional_permissions); + additionalPermissionsPreference.setOnPreferenceClickListener(preference -> { + ManageCustomPermissionsFragment frag = + new ManageCustomPermissionsFragment(); + frag.setTargetFragment(ManageStandardPermissionsFragment.this, 0); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(android.R.id.content, frag); + ft.addToBackStack(null); + ft.commit(); + return true; + }); + + screen.addPreference(additionalPermissionsPreference); + } + + additionalPermissionsPreference.setSummary(getResources().getQuantityString( + R.plurals.additional_permissions_more, numExtraPermissions, + numExtraPermissions)); + } + } +} diff --git a/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java b/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java new file mode 100644 index 00000000..61e4fb9f --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2016 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. +*/ + +package com.android.packageinstaller.permission.ui.handheld; + +import android.content.Context; +import android.preference.SwitchPreference; +import android.view.View; +import android.widget.Switch; + +class MultiTargetSwitchPreference extends SwitchPreference { + private View.OnClickListener mSwitchOnClickLister; + + public MultiTargetSwitchPreference(Context context) { + super(context); + } + + public void setCheckedOverride(boolean checked) { + super.setChecked(checked); + } + + @Override + public void setChecked(boolean checked) { + // If double target behavior is enabled do nothing + if (mSwitchOnClickLister == null) { + super.setChecked(checked); + } + } + + public void setSwitchOnClickListener(View.OnClickListener listener) { + mSwitchOnClickLister = listener; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + Switch switchView = (Switch) view.findViewById( + com.android.internal.R.id.switch_widget); + if (mSwitchOnClickLister != null) { + switchView.setOnClickListener(mSwitchOnClickLister); + final int padding = (int) ((view.getMeasuredHeight() + - switchView.getMeasuredHeight()) / 2 + 0.5f); + switchView.setPadding(padding, padding, 0, padding); + } + } +}
\ No newline at end of file diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java index 899c3c2c..f4dceb76 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java @@ -15,6 +15,8 @@ */ package com.android.packageinstaller.permission.ui.handheld; +import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; + import android.app.ActionBar; import android.app.AlertDialog; import android.app.Fragment; @@ -34,6 +36,7 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; + import com.android.packageinstaller.DeviceUtils; import com.android.packageinstaller.R; import com.android.packageinstaller.permission.model.AppPermissionGroup; @@ -49,8 +52,6 @@ import com.android.settingslib.RestrictedLockUtils; import java.util.ArrayList; import java.util.List; -import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; - public final class PermissionAppsFragment extends PermissionsFrameFragment implements Callback, Preference.OnPreferenceChangeListener { @@ -58,6 +59,9 @@ public final class PermissionAppsFragment extends PermissionsFrameFragment imple private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 1; private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem"; + private static final String SHOW_SYSTEM_KEY = PermissionAppsFragment.class.getName() + + KEY_SHOW_SYSTEM_PREFS; + public static PermissionAppsFragment newInstance(String permissionName) { return setPermissionName(new PermissionAppsFragment(), permissionName); } @@ -87,6 +91,11 @@ public final class PermissionAppsFragment extends PermissionsFrameFragment imple @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + mShowSystem = savedInstanceState.getBoolean(SHOW_SYSTEM_KEY); + } + setLoading(true /* loading */, false /* animate */); setHasOptionsMenu(true); final ActionBar ab = getActivity().getActionBar(); @@ -101,6 +110,13 @@ public final class PermissionAppsFragment extends PermissionsFrameFragment imple } @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putBoolean(SHOW_SYSTEM_KEY, mShowSystem); + } + + @Override public void onResume() { super.onResume(); mPermissionApps.refresh(true); diff --git a/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java b/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java index 44a7f471..a5dde173 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java @@ -28,7 +28,7 @@ import com.android.settingslib.RestrictedLockUtils; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; -public class RestrictedSwitchPreference extends SwitchPreference { +public class RestrictedSwitchPreference extends MultiTargetSwitchPreference { private final Context mContext; private boolean mDisabledByAdmin; private EnforcedAdmin mEnforcedAdmin; |