summaryrefslogtreecommitdiffstats
path: root/src/com/android/packageinstaller
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/packageinstaller')
-rw-r--r--src/com/android/packageinstaller/permission/model/AppPermissionGroup.java22
-rw-r--r--src/com/android/packageinstaller/permission/model/Permission.java4
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionApps.java21
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionGroups.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java71
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java129
-rw-r--r--src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java50
-rw-r--r--src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java183
-rw-r--r--src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java15
-rw-r--r--src/com/android/packageinstaller/permission/utils/Utils.java4
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 :