summaryrefslogtreecommitdiff
path: root/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
diff options
context:
space:
mode:
authorJordan Jozwiak <jjoz@google.com>2021-09-17 14:56:37 -0700
committerJordan Jozwiak <jjoz@google.com>2021-09-21 15:05:05 -0700
commit48a7a7be85e1205d27157e238b74cae6994e3791 (patch)
tree21e0ab43ccf35172ae19b33f1ab138fad98b5e10 /PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
parentc92fbbeb8ce40bbe18f1070a7733bd3abeb4f7d5 (diff)
downloadPermission-48a7a7be85e1205d27157e238b74cae6994e3791.tar.gz
Modernize AutoAppPermissions screen
Use the latest ViewModel to fix a bug where the permission grant state shows incorrectly. This update also surfaces the last access time for permission groups, as used in conjunction with the Privacy Dashboard. AppPermissions before: https://hsv.googleplex.com/6663132795633664 AppPermissions after: https://hsv.googleplex.com/6732901947277312 Additional permissions before: https://hsv.googleplex.com/5000443337900032 Additional permissions after: https://hsv.googleplex.com/4605919050596352 Bug: 199932178 Bug: 179383241 Test: Manual testing Change-Id: I1916eb372e2ef5d2cb2c057bd1706c97affabe1d
Diffstat (limited to 'PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java')
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java338
1 files changed, 170 insertions, 168 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
index b26e30ba3..539ac1787 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
@@ -24,55 +24,62 @@ import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__DENIED;
import static com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_CALLER_NAME;
+import static java.util.concurrent.TimeUnit.DAYS;
+
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
-import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
-import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-import com.android.car.ui.utils.ViewUtils;
+import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.PermissionControllerStatsLog;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.auto.AutoSettingsFrameFragment;
-import com.android.permissioncontroller.permission.model.AppPermissionGroup;
-import com.android.permissioncontroller.permission.model.AppPermissions;
+import com.android.permissioncontroller.permission.model.AppPermissionUsage;
+import com.android.permissioncontroller.permission.model.PermissionUsages;
import com.android.permissioncontroller.permission.ui.Category;
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel;
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModelFactory;
-import com.android.permissioncontroller.permission.utils.Utils;
+import com.android.permissioncontroller.permission.utils.KotlinUtils;
import java.text.Collator;
+import java.time.Instant;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/** Screen to show the permissions for a specific application. */
-public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
+public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment implements
+ PermissionUsages.PermissionsUsagesChangeCallback {
private static final String LOG_TAG = AutoAppPermissionsFragment.class.getSimpleName();
- private static final String KEY_ALLOWED_PERMISSIONS_GROUP = "allowed_permissions_group";
- private static final String KEY_DENIED_PERMISSIONS_GROUP = "denied_permissions_group";
+ private static final String IS_SYSTEM_PERMS_SCREEN = "_is_system_screen";
+ private static final String KEY_ALLOWED_PERMISSIONS_GROUP = Category.ALLOWED.getCategoryName();
+ private static final String KEY_DENIED_PERMISSIONS_GROUP = Category.DENIED.getCategoryName();
private AppPermissionGroupsViewModel mViewModel;
- private AppPermissions mAppPermissions;
- private PreferenceScreen mExtraScreen;
private String mPackageName;
+ private boolean mIsFirstLoad;
+ private UserHandle mUser;
+ private PermissionUsages mPermissionUsages;
+ private List<AppPermissionUsage> mAppPermissionUsages = new ArrayList<>();
+ private boolean mIsSystemPermsScreen;
private Collator mCollator;
@@ -80,17 +87,19 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
* @return A new fragment
*/
public static AutoAppPermissionsFragment newInstance(@NonNull String packageName,
- @NonNull UserHandle userHandle, long sessionId) {
+ @NonNull UserHandle userHandle, long sessionId, boolean isSystemPermsScreen) {
return setPackageNameAndUserHandle(new AutoAppPermissionsFragment(), packageName,
- userHandle, sessionId);
+ userHandle, sessionId, isSystemPermsScreen);
}
private static <T extends Fragment> T setPackageNameAndUserHandle(@NonNull T fragment,
- @NonNull String packageName, @NonNull UserHandle userHandle, long sessionId) {
+ @NonNull String packageName, @NonNull UserHandle userHandle, long sessionId,
+ boolean isSystemPermsScreen) {
Bundle arguments = new Bundle();
arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
arguments.putParcelable(Intent.EXTRA_USER, userHandle);
arguments.putLong(EXTRA_SESSION_ID, sessionId);
+ arguments.putBoolean(IS_SYSTEM_PERMS_SCREEN, isSystemPermsScreen);
fragment.setArguments(arguments);
return fragment;
}
@@ -101,6 +110,8 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
setLoading(true);
mPackageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
+ mUser = getArguments().getParcelable(Intent.EXTRA_USER);
+ mIsSystemPermsScreen = getArguments().getBoolean(IS_SYSTEM_PERMS_SCREEN, true);
UserHandle userHandle = getArguments().getParcelable(Intent.EXTRA_USER);
Activity activity = requireActivity();
PackageInfo packageInfo = AutoPermissionsUtils.getPackageInfo(activity, mPackageName,
@@ -112,8 +123,6 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
return;
}
- mAppPermissions = new AppPermissions(activity, packageInfo, /* sortGroups= */ true,
- () -> getActivity().finish());
mCollator = Collator.getInstance(
getContext().getResources().getConfiguration().getLocales().get(0));
AppPermissionGroupsViewModelFactory factory =
@@ -122,13 +131,27 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
mViewModel = new ViewModelProvider(this, factory).get(AppPermissionGroupsViewModel.class);
setHeaderLabel(getContext().getString(R.string.app_permissions));
- setAction(getContext().getString(R.string.all_permissions), v -> showAllPermissions());
+ if (mIsSystemPermsScreen) {
+ setAction(getContext().getString(R.string.all_permissions), v -> showAllPermissions());
+ }
createPreferenceCategories(packageInfo);
mViewModel.getPackagePermGroupsLiveData().observe(this, this::updatePreferences);
if (mViewModel.getPackagePermGroupsLiveData().getValue() != null) {
updatePreferences(mViewModel.getPackagePermGroupsLiveData().getValue());
}
+
+ if (SdkLevel.isAtLeastS()) {
+ mPermissionUsages = new PermissionUsages(getContext());
+
+ long filterTimeBeginMillis = Math.max(System.currentTimeMillis()
+ - DAYS.toMillis(
+ AppPermissionGroupsViewModel.AGGREGATE_DATA_FILTER_BEGIN_DAYS),
+ Instant.EPOCH.toEpochMilli());
+ mPermissionUsages.load(null, null, filterTimeBeginMillis, Long.MAX_VALUE,
+ PermissionUsages.USAGE_FLAG_LAST, getActivity().getLoaderManager(),
+ false, false, this, false);
+ }
}
@Override
@@ -136,6 +159,22 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
}
+
+ @Override
+ @RequiresApi(Build.VERSION_CODES.S)
+ public void onPermissionUsagesChanged() {
+ if (mPermissionUsages.getUsages().isEmpty()) {
+ return;
+ }
+ if (getContext() == null) {
+ // Async result has come in after our context is gone.
+ return;
+ }
+
+ mAppPermissionUsages = new ArrayList<>(mPermissionUsages.getUsages());
+ updatePreferences(mViewModel.getPackagePermGroupsLiveData().getValue());
+ }
+
private void showAllPermissions() {
Fragment frag = AutoAllAppPermissionsFragment.newInstance(
getArguments().getString(Intent.EXTRA_PACKAGE_NAME),
@@ -167,10 +206,8 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
bindUi(packageInfo);
}
- // TODO(b/179383241): Make full use of groupMap data in this method
private void updatePreferences(
Map<Category, List<AppPermissionGroupsViewModel.GroupUiInfo>> groupMap) {
- mAppPermissions.refresh();
Context context = getPreferenceManager().getContext();
if (context == null) {
return;
@@ -185,95 +222,120 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
return;
}
- PreferenceCategory allowed = findPreference(KEY_ALLOWED_PERMISSIONS_GROUP);
- PreferenceCategory denied = findPreference(KEY_DENIED_PERMISSIONS_GROUP);
+ Map<String, Long> groupUsageLastAccessTime = new HashMap<>();
+ mViewModel.extractGroupUsageLastAccessTime(groupUsageLastAccessTime, mAppPermissionUsages,
+ mPackageName);
- allowed.removeAll();
- denied.removeAll();
+ for (Category grantCategory : groupMap.keySet()) {
+ if (Category.ASK.equals(grantCategory)) {
+ // skip ask category for auto
+ continue;
+ }
+ PreferenceCategory category = getPreferenceScreen().findPreference(
+ grantCategory.getCategoryName());
+ if (grantCategory.equals(Category.ALLOWED_FOREGROUND)) {
+ category = findPreference(Category.ALLOWED.getCategoryName());
+ }
+ int numExtraPerms = 0;
- if (mExtraScreen != null) {
- mExtraScreen.removeAll();
- mExtraScreen.addPreference(AutoPermissionsUtils.createHeaderPreference(getContext(),
- mAppPermissions.getPackageInfo().applicationInfo));
- }
+ category.removeAll();
- Preference extraPerms = new Preference(context);
- extraPerms.setIcon(R.drawable.ic_toc);
- extraPerms.setTitle(R.string.additional_permissions);
- boolean extraPermsAreAllowed = false;
- ArrayList<AppPermissionGroup> groups = new ArrayList<>(
- mAppPermissions.getPermissionGroups());
- groups.sort((x, y) -> mCollator.compare(x.getLabel(), y.getLabel()));
- allowed.setOrderingAsAdded(true);
- denied.setOrderingAsAdded(true);
+ for (AppPermissionGroupsViewModel.GroupUiInfo groupInfo : groupMap.get(grantCategory)) {
+ if (groupInfo.isSystem() == mIsSystemPermsScreen) {
+ Preference preference = createPermissionPreference(getContext(), groupInfo,
+ groupUsageLastAccessTime);
+ category.addPreference(preference);
+ } else if (!groupInfo.isSystem()) {
+ numExtraPerms++;
+ }
+ }
+
- for (int i = 0; i < groups.size(); i++) {
- AppPermissionGroup group = groups.get(i);
- if (!Utils.shouldShowPermission(getContext(), group)) {
- continue;
+ if (numExtraPerms > 0) {
+ setAdditionalPermissionsPreference(category, numExtraPerms, context);
}
- boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG);
-
- Preference preference = createPermissionPreference(getContext(), group);
- if (isPlatform) {
- PreferenceCategory category =
- group.areRuntimePermissionsGranted() ? allowed : denied;
- category.addPreference(preference);
- } else {
- if (mExtraScreen == null) {
- mExtraScreen = getPreferenceManager().createPreferenceScreen(context);
- mExtraScreen.addPreference(
- AutoPermissionsUtils.createHeaderPreference(getContext(),
- mAppPermissions.getPackageInfo().applicationInfo));
- }
- mExtraScreen.addPreference(preference);
- if (group.areRuntimePermissionsGranted()) {
- extraPermsAreAllowed = true;
- }
+ if (category.getPreferenceCount() == 0) {
+ setNoPermissionPreference(category, grantCategory, context);
}
- }
- if (mExtraScreen != null) {
- extraPerms.setOnPreferenceClickListener(preference -> {
- AutoAppPermissionsFragment.AdditionalPermissionsFragment
- frag = new AutoAppPermissionsFragment.AdditionalPermissionsFragment();
- setPackageNameAndUserHandle(frag,
- getArguments().getString(Intent.EXTRA_PACKAGE_NAME),
- getArguments().getParcelable(Intent.EXTRA_USER),
- getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID));
- frag.setTargetFragment(AutoAppPermissionsFragment.this, 0);
- getFragmentManager().beginTransaction()
- .replace(android.R.id.content, frag)
- .addToBackStack(null)
- .commit();
- return true;
- });
- // Delete 1 to account for app header preference.
- int count = mExtraScreen.getPreferenceCount() - 1;
- extraPerms.setSummary(getResources().getQuantityString(
- R.plurals.additional_permissions_more, count,
- count));
- PreferenceCategory category = extraPermsAreAllowed ? allowed : denied;
- category.addPreference(extraPerms);
+ KotlinUtils.INSTANCE.sortPreferenceGroup(category, this::comparePreferences, false);
}
- if (allowed.getPreferenceCount() == 0) {
- Preference empty = new Preference(context);
- empty.setTitle(getString(R.string.no_permissions_allowed));
- empty.setSelectable(false);
- allowed.addPreference(empty);
+
+ if (mIsFirstLoad) {
+ logAppPermissionsFragmentView();
+ mIsFirstLoad = false;
}
- if (denied.getPreferenceCount() == 0) {
- Preference empty = new Preference(context);
- empty.setTitle(getString(R.string.no_permissions_denied));
- empty.setSelectable(false);
- denied.addPreference(empty);
+ }
+
+ private Preference createPermissionPreference(Context context,
+ AppPermissionGroupsViewModel.GroupUiInfo groupInfo,
+ Map<String, Long> groupUsageLastAccessTime) {
+ String groupName = groupInfo.getGroupName();
+ Preference preference = new Preference(context);
+ preference.setTitle(KotlinUtils.INSTANCE.getPermGroupLabel(context, groupName));
+ preference.setIcon(KotlinUtils.INSTANCE.getPermGroupIcon(context, groupName));
+ preference.setKey(groupName);
+ String summary = mViewModel.getPreferenceSummary(groupInfo, context,
+ groupUsageLastAccessTime.get(groupName));
+ if (!summary.isEmpty()) {
+ preference.setSummary(summary);
}
+ preference.setOnPreferenceClickListener(pref -> {
+ Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
+ intent.putExtra(Intent.EXTRA_PERMISSION_NAME, groupName);
+ intent.putExtra(Intent.EXTRA_USER, mUser);
+ intent.putExtra(EXTRA_CALLER_NAME, AutoAppPermissionsFragment.class.getName());
+ context.startActivity(intent);
+ return true;
+ });
+ return preference;
+ }
+
+ private void setAdditionalPermissionsPreference(PreferenceCategory category, int numExtraPerms,
+ Context context) {
+ Preference extraPerms = new Preference(context);
+ extraPerms.setIcon(R.drawable.ic_toc);
+ extraPerms.setTitle(R.string.additional_permissions);
+ extraPerms.setOnPreferenceClickListener(preference -> {
+ AutoAppPermissionsFragment
+ frag = AutoAppPermissionsFragment.newInstance(mPackageName, mUser,
+ getArguments().getLong(EXTRA_SESSION_ID), false);
+ frag.setTargetFragment(AutoAppPermissionsFragment.this, 0);
+ getFragmentManager().beginTransaction()
+ .replace(android.R.id.content, frag)
+ .addToBackStack(null)
+ .commit();
+ return true;
+ });
+ extraPerms.setSummary(getResources().getQuantityString(
+ R.plurals.additional_permissions_more, numExtraPerms,
+ numExtraPerms));
+ category.addPreference(extraPerms);
+ }
+
+ private void setNoPermissionPreference(PreferenceCategory category, Category grantCategory,
+ Context context) {
+ Preference empty = new Preference(context);
+ empty.setKey(getString(grantCategory.equals(Category.DENIED)
+ ? R.string.no_permissions_denied : R.string.no_permissions_allowed));
+ empty.setTitle(empty.getKey());
+ empty.setSelectable(false);
+ category.addPreference(empty);
+ }
- setLoading(false);
- logAppPermissionsFragmentView();
+ private int comparePreferences(Preference lhs, Preference rhs) {
+ String additionalTitle = lhs.getContext().getString(R.string.additional_permissions);
+ if (lhs.getTitle().equals(additionalTitle)) {
+ return 1;
+ } else if (rhs.getTitle().equals(additionalTitle)) {
+ return -1;
+ }
+ return mCollator.compare(lhs.getTitle().toString(),
+ rhs.getTitle().toString());
}
private void logAppPermissionsFragmentView() {
@@ -293,13 +355,14 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
int numAllowed = allowed.getPreferenceCount();
for (int i = 0; i < numAllowed; i++) {
Preference preference = allowed.getPreference(i);
- if (preference.getSummary() == null) {
+ if (preference.getTitle().equals(getString(R.string.no_permissions_allowed))) {
// R.string.no_permission_allowed was added to PreferenceCategory
continue;
}
int category = APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__ALLOWED;
- if (permissionSubtitleOnlyInForeground.contentEquals(preference.getSummary())) {
+ if (preference.getSummary() != null
+ && permissionSubtitleOnlyInForeground.contentEquals(preference.getSummary())) {
category = APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__ALLOWED_FOREGROUND;
}
@@ -311,7 +374,7 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
int numDenied = denied.getPreferenceCount();
for (int i = 0; i < numDenied; i++) {
Preference preference = denied.getPreference(i);
- if (preference.getSummary() == null) {
+ if (preference.getTitle().equals(getString(R.string.no_permissions_denied))) {
// R.string.no_permission_denied was added to PreferenceCategory
continue;
}
@@ -322,78 +385,17 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment {
private void logAppPermissionsFragmentViewEntry(
long sessionId, long viewId, String permissionGroupName, int category) {
+ Integer uid = KotlinUtils.INSTANCE.getPackageUid(getActivity().getApplication(),
+ mPackageName, mUser);
+ if (uid == null) {
+ return;
+ }
PermissionControllerStatsLog.write(APP_PERMISSIONS_FRAGMENT_VIEWED, sessionId, viewId,
- permissionGroupName, mAppPermissions.getPackageInfo().applicationInfo.uid,
- mAppPermissions.getPackageInfo().packageName, category);
+ permissionGroupName, uid, mPackageName, category);
Log.v(LOG_TAG, "AutoAppPermissionFragment view logged with sessionId=" + sessionId
+ " viewId=" + viewId + " permissionGroupName=" + permissionGroupName + " uid="
- + mAppPermissions.getPackageInfo().applicationInfo.uid + " packageName="
- + mAppPermissions.getPackageInfo().packageName + " category=" + category);
- }
-
- private Preference createPermissionPreference(Context context, AppPermissionGroup group) {
- Preference preference = new Preference(context);
- Drawable icon = Utils.loadDrawable(context.getPackageManager(),
- group.getIconPkg(), group.getIconResId());
- preference.setKey(group.getName());
- preference.setTitle(group.getFullLabel());
- preference.setIcon(Utils.applyTint(context, icon, android.R.attr.colorControlNormal));
- preference.setSummary(getPreferenceSummary(group));
- preference.setOnPreferenceClickListener(pref -> {
- Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, group.getApp().packageName);
- intent.putExtra(Intent.EXTRA_PERMISSION_NAME, group.getPermissions().get(0).getName());
- intent.putExtra(Intent.EXTRA_USER, group.getUser());
- intent.putExtra(EXTRA_CALLER_NAME, AutoAppPermissionsFragment.class.getName());
- context.startActivity(intent);
- return true;
- });
- return preference;
- }
-
- private String getPreferenceSummary(AppPermissionGroup group) {
- return getGroupSummary(group);
- }
-
- private String getGroupSummary(AppPermissionGroup group) {
- if (group.hasPermissionWithBackgroundMode() && group.areRuntimePermissionsGranted()) {
- AppPermissionGroup backgroundGroup = group.getBackgroundPermissions();
- if (backgroundGroup == null || !backgroundGroup.areRuntimePermissionsGranted()) {
- return getContext().getString(R.string.permission_subtitle_only_in_foreground);
- }
- }
- return "";
- }
-
- /**
- * Class that shows additional permissions.
- */
- public static class AdditionalPermissionsFragment extends AutoSettingsFrameFragment {
- AutoAppPermissionsFragment mOuterFragment;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- // Set this before calling super.onCreate as it is needed in onCreatePreferences
- // (which is called from super.onCreate).
- mOuterFragment = (AutoAppPermissionsFragment) getTargetFragment();
- super.onCreate(savedInstanceState);
- setHeaderLabel(mOuterFragment.getHeaderLabel());
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- // initially focus on focus parking view and then shift focus to recyclerview once it
- // has loaded
- ViewUtils.hideFocus(getListView().getRootView());
- ViewUtils.initFocus((ViewUtils.LazyLayoutView) getListView());
- }
-
- @Override
- public void onCreatePreferences(Bundle bundle, String s) {
- setPreferenceScreen(mOuterFragment.mExtraScreen);
- }
+ + uid + " packageName="
+ + mPackageName + " category=" + category);
}
}