diff options
Diffstat (limited to 'src')
11 files changed, 342 insertions, 161 deletions
diff --git a/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java b/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java index 6bd15aff..8e86678d 100644 --- a/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java +++ b/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java @@ -207,6 +207,18 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup> return mAppSupportsRuntimePermissions; } + + public boolean hasGrantedByDefaultPermission() { + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = mPermissions.valueAt(i); + if (permission.isGrantedByDefault()) { + return true; + } + } + return false; + } + public boolean hasAppOpPermission() { final int permissionCount = mPermissions.size(); for (int i = 0; i < permissionCount; i++) { @@ -258,15 +270,15 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup> for (int i = 0; i < permissionCount; i++) { Permission permission = mPermissions.valueAt(i); if (mAppSupportsRuntimePermissions) { - if (!permission.isGranted()) { - return false; + if (permission.isGranted()) { + return true; } } else if (permission.isGranted() && permission.getAppOp() - != AppOpsManager.OP_NONE && !permission.isAppOpAllowed()) { - return false; + != AppOpsManager.OP_NONE && permission.isAppOpAllowed()) { + return true; } } - return true; + return false; } public boolean grantRuntimePermissions(boolean fixedByTheUser) { diff --git a/src/com/android/packageinstaller/permission/model/Permission.java b/src/com/android/packageinstaller/permission/model/Permission.java index da234bdb..1be4e75b 100644 --- a/src/com/android/packageinstaller/permission/model/Permission.java +++ b/src/com/android/packageinstaller/permission/model/Permission.java @@ -88,6 +88,10 @@ public final class Permission { return (mFlags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; } + public boolean isGrantedByDefault() { + return (mFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0; + } + public void setUserSet(boolean userSet) { if (userSet) { mFlags |= PackageManager.FLAG_PERMISSION_USER_SET; diff --git a/src/com/android/packageinstaller/permission/model/PermissionApps.java b/src/com/android/packageinstaller/permission/model/PermissionApps.java index 417e3274..8c537155 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionApps.java +++ b/src/com/android/packageinstaller/permission/model/PermissionApps.java @@ -22,7 +22,6 @@ import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PermissionInfo; -import android.graphics.LightingColorFilter; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.UserHandle; @@ -160,16 +159,21 @@ public class PermissionApps { for (int j = 0; j < app.requestedPermissions.length; j++) { String requestedPerm = app.requestedPermissions[j]; - boolean requestsPermissionInGroup = false; + PermissionInfo requestedPermissionInfo = null; for (PermissionInfo groupPermInfo : groupPermInfos) { - if (groupPermInfo.name.equals(requestedPerm)) { - requestsPermissionInGroup = true; + if (requestedPerm.equals(groupPermInfo.name)) { + requestedPermissionInfo = groupPermInfo; break; } } - if (!requestsPermissionInGroup) { + if (requestedPermissionInfo == null) { + continue; + } + + if (requestedPermissionInfo.protectionLevel + != PermissionInfo.PROTECTION_DANGEROUS) { continue; } @@ -265,8 +269,7 @@ public class PermissionApps { } else { mIcon = mContext.getDrawable(com.android.internal.R.drawable.ic_perm_device_info); } - LightingColorFilter filter = new LightingColorFilter(0, 0xffffffff); - mIcon.setColorFilter(filter); + mIcon = Utils.applyTint(mContext, mIcon, android.R.attr.colorControlNormal); } public static class PermissionApp implements Comparable<PermissionApp> { @@ -321,6 +324,10 @@ public class PermissionApps { return mAppPermissionGroup.isSystemFixed(); } + public boolean hasGrantedByDefaultPermissions() { + return mAppPermissionGroup.hasGrantedByDefaultPermission(); + } + public boolean hasRuntimePermissions() { return mAppPermissionGroup.hasRuntimePermission(); } diff --git a/src/com/android/packageinstaller/permission/model/PermissionGroups.java b/src/com/android/packageinstaller/permission/model/PermissionGroups.java index 62477b88..8ed3ebb0 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionGroups.java +++ b/src/com/android/packageinstaller/permission/model/PermissionGroups.java @@ -158,7 +158,7 @@ public final class PermissionGroups implements LoaderCallbacks<List<PermissionGr Set<String> requestedPermissions = new ArraySet<>(); for (PackageInfo installedPackage : installedPackages) { if (installedPackage.requestedPermissions == null) { - break; + continue; } for (String requestedPermission : installedPackage.requestedPermissions) { requestedPermissions.add(requestedPermission); diff --git a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java index d88b9adc..03be3915 100644 --- a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java @@ -21,6 +21,7 @@ import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.app.FragmentTransaction; +import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; @@ -30,21 +31,19 @@ import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; -import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceScreen; -import android.preference.SwitchPreference; import android.provider.Settings; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.Preference.OnPreferenceChangeListener; +import android.support.v7.preference.Preference.OnPreferenceClickListener; +import android.support.v7.preference.PreferenceScreen; import android.util.Log; -import android.view.LayoutInflater; 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.ListView; import android.widget.TextView; import android.widget.Toast; @@ -83,6 +82,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setLoading(true, false); mHasConfirmedRevoke = false; setHasOptionsMenu(true); final ActionBar ab = getActivity().getActionBar(); @@ -115,21 +115,6 @@ public final class AppPermissionsFragment extends SettingsWithHeader } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, - false); - ViewGroup prefsContainer = (ViewGroup) rootView.findViewById(R.id.prefs_container); - if (prefsContainer == null) { - prefsContainer = rootView; - } - prefsContainer.addView(super.onCreateView(inflater, prefsContainer, savedInstanceState)); - View emptyView = rootView.findViewById(R.id.no_permissions); - ((ListView) rootView.findViewById(android.R.id.list)).setEmptyView(emptyView); - return rootView; - } - - @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); bindUi(); @@ -199,25 +184,19 @@ public final class AppPermissionsFragment extends SettingsWithHeader } private void bindPermissionsUi() { - final Activity activity = getActivity(); - - if (activity == null) { + Context context = getPreferenceManager().getContext(); + if (context == null) { return; } PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(activity); - setPreferenceScreen(screen); - } else { - screen.removeAll(); - } + screen.removeAll(); if (mExtraScreen != null) { mExtraScreen.removeAll(); } - final Preference extraPerms = new Preference(activity); + final Preference extraPerms = new Preference(context); extraPerms.setIcon(R.drawable.ic_toc); extraPerms.setTitle(R.string.additional_permissions); @@ -227,14 +206,17 @@ public final class AppPermissionsFragment extends SettingsWithHeader continue; } - SwitchPreference preference = new SwitchPreference(activity); + SwitchPreference preference = new SwitchPreference(context); preference.setOnPreferenceChangeListener(this); preference.setKey(group.getName()); - Drawable icon = Utils.loadDrawable(activity.getPackageManager(), + 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()) { + preference.setSummary(getString(R.string.permission_summary_enforced_by_policy)); + } preference.setPersistent(false); preference.setEnabled(!group.isPolicyFixed()); preference.setChecked(group.areRuntimePermissionsGranted()); @@ -243,7 +225,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader screen.addPreference(preference); } else { if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(activity); + mExtraScreen = getPreferenceManager().createPreferenceScreen(context); } mExtraScreen.addPreference(preference); } @@ -262,10 +244,14 @@ public final class AppPermissionsFragment extends SettingsWithHeader return true; } }); - extraPerms.setSummary(getString(R.string.additional_permissions_more, - mExtraScreen.getPreferenceCount())); + int count = mExtraScreen.getPreferenceCount(); + extraPerms.setSummary(getResources().getQuantityString( + R.plurals.additional_permissions_more, count, count)); screen.addPreference(extraPerms); } + if (screen.getPreferenceCount() != 0) { + setLoading(false, true); + } } @Override @@ -286,10 +272,10 @@ public final class AppPermissionsFragment extends SettingsWithHeader if (newValue == Boolean.TRUE) { group.grantRuntimePermissions(false); } else { - final boolean system = group.getApp().applicationInfo.isSystemApp(); - if (system || (!group.hasRuntimePermission() && !mHasConfirmedRevoke)) { + final boolean grantedByDefault = group.hasGrantedByDefaultPermission(); + if (grantedByDefault || (!group.hasRuntimePermission() && !mHasConfirmedRevoke)) { new AlertDialog.Builder(getContext()) - .setMessage(system ? R.string.system_warning + .setMessage(grantedByDefault ? R.string.system_warning : R.string.old_sdk_deny_warning) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.grant_dialog_button_deny, @@ -298,7 +284,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader public void onClick(DialogInterface dialog, int which) { ((SwitchPreference) preference).setChecked(false); group.revokeRuntimePermissions(false); - if (!system) { + if (!grantedByDefault) { mHasConfirmedRevoke = true; } } @@ -375,8 +361,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader public static class AdditionalPermissionsFragment extends SettingsWithHeader { @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { AppPermissionsFragment target = (AppPermissionsFragment) getTargetFragment(); setPreferenceScreen(target.mExtraScreen); // Copy the header. diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java index 6dac87cc..8ab7c454 100644 --- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java @@ -222,11 +222,11 @@ public class GrantPermissionsActivity extends Activity if (granted) { groupState.mGroup.grantRuntimePermissions(doNotAskAgain); groupState.mState = GroupState.STATE_ALLOWED; - updateGrantResults(groupState.mGroup); } else { groupState.mGroup.revokeRuntimePermissions(doNotAskAgain); groupState.mState = GroupState.STATE_DENIED; } + updateGrantResults(groupState.mGroup); } if (!showNextPermissionGroupGrantRequest()) { setResultAndFinish(); diff --git a/src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java index 00d30d19..051676a8 100644 --- a/src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java @@ -17,26 +17,23 @@ package com.android.packageinstaller.permission.ui; import android.annotation.Nullable; import android.app.ActionBar; -import android.app.Activity; import android.app.FragmentTransaction; import android.content.ActivityNotFoundException; +import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; +import android.support.v7.preference.Preference; +import android.support.v7.preference.Preference.OnPreferenceClickListener; +import android.support.v7.preference.PreferenceScreen; import android.util.ArraySet; import android.util.Log; -import android.view.LayoutInflater; 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.ListView; import android.widget.TextView; import com.android.packageinstaller.R; @@ -48,7 +45,7 @@ import com.android.packageinstaller.permission.utils.Utils; import java.util.List; -public final class ManagePermissionsFragment extends PreferenceFragment +public final class ManagePermissionsFragment extends PermissionsFrameFragment implements PermissionGroups.PermissionsGroupsChangeCallback, OnPreferenceClickListener { private static final String LOG_TAG = "ManagePermissionsFragment"; @@ -71,6 +68,7 @@ public final class ManagePermissionsFragment extends PreferenceFragment @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); + setLoading(true, false); setHasOptionsMenu(true); final ActionBar ab = getActivity().getActionBar(); if (ab != null) { @@ -146,68 +144,55 @@ public final class ManagePermissionsFragment extends PreferenceFragment } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, - false); - ViewGroup prefsContainer = (ViewGroup) rootView.findViewById(R.id.prefs_container); - if (prefsContainer == null) { - prefsContainer = rootView; - } - prefsContainer.addView(super.onCreateView(inflater, prefsContainer, savedInstanceState)); - View emptyView = rootView.findViewById(R.id.no_permissions); - ((ListView) rootView.findViewById(android.R.id.list)).setEmptyView(emptyView); - return rootView; - } - - @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - updatePermissionsUi(); + bindPermissionUi(getActivity(), getView()); } - private void updatePermissionsUi() { - Activity activity = getActivity(); - - if (activity == null) { + private static void bindPermissionUi(@Nullable Context context, @Nullable View rootView) { + if (context == null || rootView == null) { return; } - final ViewGroup rootView = (ViewGroup) getView(); - if (rootView != null) { - final ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon); - if (iconView != null) { - // Set the icon as the background instead of the image because ImageView - // doesn't properly scale vector drawables beyond their intrinsic size - Drawable icon = activity.getDrawable(R.drawable.ic_lock); - icon.setTint(activity.getColor(R.color.off_white)); - iconView.setBackground(icon); - } - final TextView titleView = (TextView) rootView.findViewById(R.id.lb_title); - if (titleView != null) { - titleView.setText(R.string.app_permissions); - } - final TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb); - if (breadcrumbView != null) { - breadcrumbView.setText(R.string.app_permissions_breadcrumb); - } + ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon); + if (iconView != null) { + // Set the icon as the background instead of the image because ImageView + // doesn't properly scale vector drawables beyond their intrinsic size + Drawable icon = context.getDrawable(R.drawable.ic_lock); + icon.setTint(context.getColor(R.color.off_white)); + iconView.setBackground(icon); + } + TextView titleView = (TextView) rootView.findViewById(R.id.lb_title); + if (titleView != null) { + titleView.setText(R.string.app_permissions); } + TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb); + if (breadcrumbView != null) { + breadcrumbView.setText(R.string.app_permissions_breadcrumb); + } + } - List<PermissionGroup> groups = mPermissions.getGroups(); + private void updatePermissionsUi() { + Context context = getPreferenceManager().getContext(); + if (context == null) { + return; + } + List<PermissionGroup> groups = mPermissions.getGroups(); PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(activity); - setPreferenceScreen(screen); - } + int uiModeType = getResources().getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK; + boolean isTelevision = uiModeType == Configuration.UI_MODE_TYPE_TELEVISION; // Use this to speed up getting the info for all of the PermissionApps below. // Create a new one for each refresh to make sure it has fresh data. PmCache cache = new PmCache(getContext().getPackageManager()); for (PermissionGroup group : groups) { - // Show legacy permissions only if the user chose that. - if (!mShowLegacyPermissions && group.getDeclaringPackage().equals(OS_PKG) - && !Utils.isModernPermissionGroup(group.getName())) { + boolean isModernGroup = Utils.isModernPermissionGroup(group.getName()); + boolean isSystemPermission = group.getDeclaringPackage().equals(OS_PKG); + + // Show legacy permissions only if the user chose that, except + // on TV, where they get grouped into the extra screen. + if (!mShowLegacyPermissions && !isTelevision && isSystemPermission && !isModernGroup) { continue; } @@ -216,20 +201,20 @@ public final class ManagePermissionsFragment extends PreferenceFragment preference = mExtraScreen.findPreference(group.getName()); } if (preference == null) { - preference = new Preference(activity, null); + preference = new Preference(context); preference.setOnPreferenceClickListener(this); preference.setKey(group.getName()); - preference.setIcon(Utils.applyTint(activity, group.getIcon(), + 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 (group.getDeclaringPackage().equals(OS_PKG)) { + if (isSystemPermission && (isModernGroup || !isTelevision)) { screen.addPreference(preference); } else { if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(activity); + mExtraScreen = getPreferenceManager().createPreferenceScreen(context); } mExtraScreen.addPreference(preference); } @@ -252,9 +237,10 @@ public final class ManagePermissionsFragment extends PreferenceFragment if (mExtraScreen != null && mExtraScreen.getPreferenceCount() > 0 && screen.findPreference(EXTRA_PREFS_KEY) == null) { - Preference extraScreenPreference = new Preference(activity); + Preference extraScreenPreference = new Preference(context); extraScreenPreference.setKey(EXTRA_PREFS_KEY); - extraScreenPreference.setIcon(R.drawable.ic_toc); + extraScreenPreference.setIcon(Utils.applyTint(context, R.drawable.ic_toc, + android.R.attr.colorControlNormal)); extraScreenPreference.setTitle(R.string.additional_permissions); extraScreenPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override @@ -268,18 +254,21 @@ public final class ManagePermissionsFragment extends PreferenceFragment return true; } }); - extraScreenPreference.setSummary(getString(R.string.additional_permissions_more, - mExtraScreen.getPreferenceCount())); + int count = mExtraScreen.getPreferenceCount(); + extraScreenPreference.setSummary(getResources().getQuantityString( + R.plurals.additional_permissions_more, count, count)); screen.addPreference(extraScreenPreference); } + if (screen.getPreferenceCount() != 0) { + setLoading(false, true); + } } - public static class AdditionalPermissionsFragment extends PreferenceFragment { + public static class AdditionalPermissionsFragment extends PermissionsFrameFragment { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); getActivity().setTitle(R.string.additional_permissions); - setPreferenceScreen(((ManagePermissionsFragment) getTargetFragment()).mExtraScreen); setHasOptionsMenu(true); } @@ -299,5 +288,15 @@ public final class ManagePermissionsFragment extends PreferenceFragment return super.onOptionsItemSelected(item); } + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + bindPermissionUi(getActivity(), getView()); + } + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferenceScreen(((ManagePermissionsFragment) getTargetFragment()).mExtraScreen); + } } } diff --git a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java index ae7560e8..92c53fb6 100644 --- a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java @@ -24,21 +24,18 @@ import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; -import android.preference.SwitchPreference; +import android.support.v14.preference.SwitchPreference; import android.support.v4.util.ArrayMap; +import android.support.v7.preference.Preference; +import android.support.v7.preference.Preference.OnPreferenceChangeListener; +import android.support.v7.preference.PreferenceScreen; import android.util.ArraySet; -import android.view.LayoutInflater; 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.ListView; import android.widget.TextView; import com.android.packageinstaller.R; @@ -53,7 +50,7 @@ import com.android.packageinstaller.permission.utils.Utils; import java.util.ArrayList; import java.util.List; -public final class PermissionAppsFragment extends PreferenceFragment implements Callback, +public final class PermissionAppsFragment extends PermissionsFrameFragment implements Callback, OnPreferenceChangeListener { private static final int MENU_SHOW_SYSTEM = Menu.FIRST; @@ -80,6 +77,7 @@ public final class PermissionAppsFragment extends PreferenceFragment implements @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setLoading(true, false); setHasOptionsMenu(true); final ActionBar ab = getActivity().getActionBar(); if (ab != null) { @@ -127,19 +125,8 @@ public final class PermissionAppsFragment extends PreferenceFragment implements } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, - false); - ViewGroup prefsContainer = (ViewGroup) rootView.findViewById(R.id.prefs_container); - if (prefsContainer == null) { - prefsContainer = rootView; - } - prefsContainer.addView(super.onCreateView(inflater, prefsContainer, savedInstanceState)); - TextView emptyView = (TextView) rootView.findViewById(R.id.no_permissions); - emptyView.setText(R.string.no_apps); - ((ListView) rootView.findViewById(android.R.id.list)).setEmptyView(emptyView); - return rootView; + protected void onSetEmptyText(TextView textView) { + textView.setText(R.string.no_apps); } @Override @@ -177,17 +164,13 @@ public final class PermissionAppsFragment extends PreferenceFragment implements @Override public void onPermissionsLoaded(PermissionApps permissionApps) { - Context context = getActivity(); + Context context = getPreferenceManager().getContext(); if (context == null) { return; } PreferenceScreen preferences = getPreferenceScreen(); - if (preferences == null) { - preferences = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(preferences); - } preferences.removeAll(); for (PermissionApp app : permissionApps.getApps()) { if (!Utils.shouldShowPermission(app)) { @@ -203,17 +186,22 @@ public final class PermissionAppsFragment extends PreferenceFragment implements } if (pref == null) { pref = new SwitchPreference(context); - pref.setLayoutResource(R.layout.preference_app); pref.setOnPreferenceChangeListener(this); pref.setKey(app.getKey()); pref.setIcon(app.getIcon()); pref.setTitle(app.getLabel()); + if (app.isPolicyFixed()) { + pref.setSummary(getString(R.string.permission_summary_enforced_by_policy)); + } pref.setPersistent(false); pref.setEnabled(!app.isPolicyFixed()); preferences.addPreference(pref); } pref.setChecked(app.areRuntimePermissionsGranted()); } + if (preferences.getPreferenceCount() != 0) { + setLoading(false, true); + } } @Override @@ -233,10 +221,10 @@ public final class PermissionAppsFragment extends PreferenceFragment implements if (newValue == Boolean.TRUE) { app.grantRuntimePermissions(); } else { - final boolean system = app.getAppInfo().isSystemApp(); - if (system || (!app.hasRuntimePermissions() && !mHasConfirmedRevoke)) { + final boolean grantedByDefault = app.hasGrantedByDefaultPermissions(); + if (grantedByDefault || (!app.hasRuntimePermissions() && !mHasConfirmedRevoke)) { new AlertDialog.Builder(getContext()) - .setMessage(system ? R.string.system_warning + .setMessage(grantedByDefault ? R.string.system_warning : R.string.old_sdk_deny_warning) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.grant_dialog_button_deny, @@ -245,7 +233,7 @@ public final class PermissionAppsFragment extends PreferenceFragment implements public void onClick(DialogInterface dialog, int which) { ((SwitchPreference) preference).setChecked(false); app.revokeRuntimePermissions(); - if (!system) { + if (!grantedByDefault) { mHasConfirmedRevoke = true; } } diff --git a/src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java b/src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java new file mode 100644 index 00000000..88eda41f --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java @@ -0,0 +1,183 @@ +package com.android.packageinstaller.permission.ui; + +import android.annotation.Nullable; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.v14.preference.PreferenceFragment; +import android.support.v17.leanback.widget.VerticalGridView; +import android.support.v7.preference.PreferenceScreen; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.AdapterDataObserver; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; +import android.view.animation.AnimationUtils; +import android.widget.TextView; + +import com.android.packageinstaller.R; + +public abstract class PermissionsFrameFragment extends PreferenceFragment { + + private static final float WINDOW_ALIGNMENT_OFFSET_PERCENT = 50; + + private ViewGroup mPreferencesContainer; + + // TV-specific instance variables + @Nullable private VerticalGridView mGridView; + + private View mLoadingView; + private ViewGroup mPrefsView; + private boolean mIsLoading; + + /** + * Returns the view group that holds the preferences objects. This will + * only be set after {@link #onCreateView} has been called. + */ + protected final ViewGroup getPreferencesContainer() { + return mPreferencesContainer; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, + false); + mPrefsView = (ViewGroup) rootView.findViewById(R.id.prefs_container); + if (mPrefsView == null) { + mPrefsView = rootView; + } + mLoadingView = rootView.findViewById(R.id.loading_container); + mPreferencesContainer = (ViewGroup) super.onCreateView( + inflater, mPrefsView, savedInstanceState); + setLoading(mIsLoading, false, true /* force */); + mPrefsView.addView(mPreferencesContainer); + return rootView; + } + + @Override + public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { + PreferenceScreen preferences = getPreferenceScreen(); + if (preferences == null) { + preferences = getPreferenceManager().createPreferenceScreen(getActivity()); + setPreferenceScreen(preferences); + } + } + + protected void setLoading(boolean loading, boolean animate) { + setLoading(loading, animate, false); + } + + private void setLoading(boolean loading, boolean animate, boolean force) { + if (mIsLoading != loading || force) { + mIsLoading = loading; + if (mLoadingView == null) { + return; + } + setViewShown(mPrefsView, !loading, animate); + setViewShown(mLoadingView, loading, animate); + } + } + + private void setViewShown(final View view, boolean shown, boolean animate) { + if (animate) { + Animation animation = AnimationUtils.loadAnimation(getContext(), + shown ? android.R.anim.fade_in : android.R.anim.fade_out); + if (shown) { + view.setVisibility(View.VISIBLE); + } else { + animation.setAnimationListener(new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + view.setVisibility(View.INVISIBLE); + } + }); + } + view.startAnimation(animation); + } else { + view.clearAnimation(); + view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE); + } + } + + @Override + public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, + Bundle savedInstanceState) { + int uiMode = getResources().getConfiguration().uiMode; + if ((uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) { + mGridView = (VerticalGridView) inflater.inflate( + R.layout.leanback_preferences_list, parent, false); + mGridView.setWindowAlignmentOffset(0); + mGridView.setWindowAlignmentOffsetPercent(WINDOW_ALIGNMENT_OFFSET_PERCENT); + mGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE); + mGridView.setFocusScrollStrategy(VerticalGridView.FOCUS_SCROLL_ALIGNED); + return mGridView; + } else { + return super.onCreateRecyclerView(inflater, parent, savedInstanceState); + } + } + + @Override + protected RecyclerView.Adapter<?> onCreateAdapter(PreferenceScreen preferenceScreen) { + final RecyclerView.Adapter<?> adapter = super.onCreateAdapter(preferenceScreen); + + if (adapter != null) { + final TextView emptyView = (TextView) getView().findViewById(R.id.no_permissions); + onSetEmptyText(emptyView); + final RecyclerView recyclerView = getListView(); + adapter.registerAdapterDataObserver(new AdapterDataObserver() { + @Override + public void onChanged() { + checkEmpty(); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + checkEmpty(); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + checkEmpty(); + } + + private void checkEmpty() { + boolean isEmpty = adapter.getItemCount() == 0; + emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); + recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE); + if (!isEmpty && mGridView != null) { + mGridView.requestFocus(); + } + } + }); + + boolean isEmpty = adapter.getItemCount() == 0; + emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); + recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE); + if (!isEmpty && mGridView != null) { + mGridView.requestFocus(); + } + } + + return adapter; + } + + /** + * Hook for subclasses to change the default text of the empty view. + * Base implementation leaves the default empty view text. + * + * @param textView the empty text view + */ + protected void onSetEmptyText(TextView textView) { + } +} + diff --git a/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java b/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java index 74146fe6..4135af97 100644 --- a/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java +++ b/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java @@ -20,18 +20,17 @@ import android.content.Intent; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.preference.PreferenceFragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import com.android.packageinstaller.R; -public abstract class SettingsWithHeader extends PreferenceFragment implements OnClickListener { +public abstract class SettingsWithHeader extends PermissionsFrameFragment + implements OnClickListener { private View mHeader; protected Intent mInfoIntent; @@ -41,16 +40,16 @@ public abstract class SettingsWithHeader extends PreferenceFragment implements O @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - LinearLayout contentParent = - (LinearLayout) super.onCreateView(inflater, container, savedInstanceState); + ViewGroup root = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState); + int uiMode = getResources().getConfiguration().uiMode; if ((uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_TELEVISION) { - mHeader = inflater.inflate(R.layout.header, contentParent, false); - contentParent.addView(mHeader, 0); + mHeader = inflater.inflate(R.layout.header, root, false); + getPreferencesContainer().addView(mHeader, 0); updateHeader(); } - return contentParent; + return root; } public void setHeader(Drawable icon, CharSequence label, Intent infoIntent) { diff --git a/src/com/android/packageinstaller/permission/utils/Utils.java b/src/com/android/packageinstaller/permission/utils/Utils.java index 144ff774..940e3597 100644 --- a/src/com/android/packageinstaller/permission/utils/Utils.java +++ b/src/com/android/packageinstaller/permission/utils/Utils.java @@ -123,6 +123,10 @@ public class Utils { return icon; } + public static Drawable applyTint(Context context, int iconResId, int attr) { + return applyTint(context, context.getDrawable(iconResId), attr); + } + public static ArraySet<String> getLauncherPackages(Context context) { ArraySet<String> launcherPkgs = new ArraySet<>(); for (ResolveInfo info : |