diff options
author | Joel Galenson <jgalenson@google.com> | 2019-05-30 08:30:12 -0700 |
---|---|---|
committer | Joel Galenson <jgalenson@google.com> | 2019-05-30 10:08:25 -0700 |
commit | 5747740517e37ebe05209fde129cc776af4c2127 (patch) | |
tree | c7dedb624e5abb8628ca27f1dee12c55e4c00b80 /src | |
parent | 1e0e6a056130a88cf9f0325c8d3356538ea25fa7 (diff) | |
download | android_packages_apps_PackageInstaller-5747740517e37ebe05209fde129cc776af4c2127.tar.gz android_packages_apps_PackageInstaller-5747740517e37ebe05209fde129cc776af4c2127.tar.bz2 android_packages_apps_PackageInstaller-5747740517e37ebe05209fde129cc776af4c2127.zip |
Remove Permissions Hub.
Bug: 132292477
Test: View all related screens.
Change-Id: I23aecd976b51d864b198c39994736060fc7a0785
Diffstat (limited to 'src')
15 files changed, 10 insertions, 2127 deletions
diff --git a/src/com/android/packageinstaller/permission/model/PermissionUsages.java b/src/com/android/packageinstaller/permission/model/PermissionUsages.java index 0172635f..32db2077 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionUsages.java +++ b/src/com/android/packageinstaller/permission/model/PermissionUsages.java @@ -16,12 +16,6 @@ package com.android.packageinstaller.permission.model; -import android.app.AppOpsManager; -import android.app.AppOpsManager.HistoricalOps; -import android.app.AppOpsManager.HistoricalOpsRequest; -import android.app.AppOpsManager.HistoricalPackageOps; -import android.app.AppOpsManager.HistoricalUidOps; -import android.app.AppOpsManager.PackageOps; import android.app.LoaderManager; import android.app.LoaderManager.LoaderCallbacks; import android.content.AsyncTaskLoader; @@ -29,23 +23,13 @@ import android.content.Context; import android.content.Loader; import android.os.Bundle; import android.os.Process; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.packageinstaller.permission.model.AppPermissionUsage.Builder; -import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; -import com.android.packageinstaller.permission.utils.Utils; - import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; /** * Loads all permission usages for a set of apps and permission groups. @@ -142,27 +126,7 @@ public final class PermissionUsages implements LoaderCallbacks<List<AppPermissio public static @Nullable AppPermissionUsage.GroupUsage loadLastGroupUsage( @NonNull Context context, @NonNull AppPermissionGroup group) { - if (!Utils.isPermissionsHubEnabled()) { - return null; - } - final ArraySet<String> opNames = new ArraySet<>(); - final List<Permission> permissions = group.getPermissions(); - final int permCount = permissions.size(); - for (int i = 0; i < permCount; i++) { - final Permission permission = permissions.get(i); - final String opName = permission.getAppOp(); - if (opName != null) { - opNames.add(opName); - } - } - final String[] opNamesArray = opNames.toArray(new String[opNames.size()]); - final List<PackageOps> usageOps = context.getSystemService(AppOpsManager.class) - .getOpsForPackage(group.getApp().applicationInfo.uid, - group.getApp().packageName, opNamesArray); - if (usageOps == null || usageOps.isEmpty()) { - return null; - } - return new AppPermissionUsage.GroupUsage(group, usageOps.get(0), null); + return null; } private static final class UsageLoader extends AsyncTaskLoader<List<AppPermissionUsage>> { @@ -194,151 +158,7 @@ public final class PermissionUsages implements LoaderCallbacks<List<AppPermissio @Override public @NonNull List<AppPermissionUsage> loadInBackground() { - final List<PermissionGroup> groups = PermissionGroups.getPermissionGroups( - getContext(), this::isLoadInBackgroundCanceled, mGetUiInfo, - mGetNonPlatformPermissions, mFilterPermissionGroups, mFilterPackageName); - if (!Utils.isPermissionsHubEnabled()) { - return Collections.emptyList(); - } - - if (groups.isEmpty()) { - return Collections.emptyList(); - } - - final List<AppPermissionUsage> usages = new ArrayList<>(); - final ArraySet<String> opNames = new ArraySet<>(); - final ArrayMap<Pair<Integer, String>, AppPermissionUsage.Builder> usageBuilders = - new ArrayMap<>(); - - final int groupCount = groups.size(); - for (int groupIdx = 0; groupIdx < groupCount; groupIdx++) { - final PermissionGroup group = groups.get(groupIdx); - // Filter out third party permissions - if (!group.getDeclaringPackage().equals(Utils.OS_PKG)) { - continue; - } - if (!Utils.shouldShowPermissionUsage(group.getName())) { - continue; - } - - groups.add(group); - - final List<PermissionApp> permissionApps = group.getPermissionApps().getApps(); - final int appCount = permissionApps.size(); - for (int appIdx = 0; appIdx < appCount; appIdx++) { - final PermissionApp permissionApp = permissionApps.get(appIdx); - if (mFilterUid != Process.INVALID_UID - && permissionApp.getAppInfo().uid != mFilterUid) { - continue; - } - - final AppPermissionGroup appPermGroup = permissionApp.getPermissionGroup(); - if (!Utils.shouldShowPermission(getContext(), appPermGroup)) { - continue; - } - final Pair<Integer, String> usageKey = Pair.create(permissionApp.getUid(), - permissionApp.getPackageName()); - AppPermissionUsage.Builder usageBuilder = usageBuilders.get(usageKey); - if (usageBuilder == null) { - usageBuilder = new Builder(permissionApp); - usageBuilders.put(usageKey, usageBuilder); - } - usageBuilder.addGroup(appPermGroup); - final List<Permission> permissions = appPermGroup.getPermissions(); - final int permCount = permissions.size(); - for (int permIdx = 0; permIdx < permCount; permIdx++) { - final Permission permission = permissions.get(permIdx); - final String opName = permission.getAppOp(); - if (opName != null) { - opNames.add(opName); - } - } - } - } - - if (usageBuilders.isEmpty()) { - return Collections.emptyList(); - } - - final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class); - - // Get last usage data and put in a map for a quick lookup. - final ArrayMap<Pair<Integer, String>, PackageOps> lastUsages = - new ArrayMap<>(usageBuilders.size()); - final String[] opNamesArray = opNames.toArray(new String[opNames.size()]); - if ((mUsageFlags & USAGE_FLAG_LAST) != 0) { - final List<PackageOps> usageOps; - if (mFilterPackageName != null || mFilterUid != Process.INVALID_UID) { - usageOps = appOpsManager.getOpsForPackage(mFilterUid, mFilterPackageName, - opNamesArray); - } else { - usageOps = appOpsManager.getPackagesForOps(opNamesArray); - } - if (usageOps != null && !usageOps.isEmpty()) { - final int usageOpsCount = usageOps.size(); - for (int i = 0; i < usageOpsCount; i++) { - final PackageOps usageOp = usageOps.get(i); - lastUsages.put(Pair.create(usageOp.getUid(), usageOp.getPackageName()), - usageOp); - } - } - } - - if (isLoadInBackgroundCanceled()) { - return Collections.emptyList(); - } - - // Get historical usage data and put in a map for a quick lookup - final ArrayMap<Pair<Integer, String>, HistoricalPackageOps> historicalUsages = - new ArrayMap<>(usageBuilders.size()); - if ((mUsageFlags & USAGE_FLAG_HISTORICAL) != 0) { - final AtomicReference<HistoricalOps> historicalOpsRef = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder( - mFilterBeginTimeMillis, mFilterEndTimeMillis) - .setUid(mFilterUid) - .setPackageName(mFilterPackageName) - .setOpNames(new ArrayList<>(opNames)) - .setFlags(AppOpsManager.OP_FLAGS_ALL_TRUSTED) - .build(); - appOpsManager.getHistoricalOps(request, Runnable::run, - (HistoricalOps ops) -> { - historicalOpsRef.set(ops); - latch.countDown(); - }); - try { - latch.await(5, TimeUnit.DAYS); - } catch (InterruptedException ignored) {} - - final HistoricalOps historicalOps = historicalOpsRef.get(); - if (historicalOps != null) { - final int uidCount = historicalOps.getUidCount(); - for (int i = 0; i < uidCount; i++) { - final HistoricalUidOps uidOps = historicalOps.getUidOpsAt(i); - final int packageCount = uidOps.getPackageCount(); - for (int j = 0; j < packageCount; j++) { - final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(j); - historicalUsages.put( - Pair.create(uidOps.getUid(), packageOps.getPackageName()), - packageOps); - } - } - } - } - - // Construct the historical usages based on data we fetched - final int builderCount = usageBuilders.size(); - for (int i = 0; i < builderCount; i++) { - final Pair<Integer, String> key = usageBuilders.keyAt(i); - final Builder usageBuilder = usageBuilders.valueAt(i); - final PackageOps lastUsage = lastUsages.get(key); - usageBuilder.setLastUsage(lastUsage); - final HistoricalPackageOps historicalUsage = historicalUsages.get(key); - usageBuilder.setHistoricalUsage(historicalUsage); - usages.add(usageBuilder.build()); - } - - return usages; + return Collections.emptyList(); } } } diff --git a/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java b/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java index 178ac662..6427ba36 100644 --- a/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java +++ b/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java @@ -47,11 +47,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissionUsage; -import com.android.packageinstaller.permission.model.AppPermissionUsage.GroupUsage; import com.android.packageinstaller.permission.model.AppPermissions; import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.model.PermissionUsages; import com.android.packageinstaller.permission.utils.Utils; import org.xmlpull.v1.XmlPullParser; @@ -499,52 +496,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerS private @NonNull List<RuntimePermissionUsageInfo> onGetPermissionUsages( boolean countSystem, long numMillis) { - ArrayMap<String, Integer> groupUsers = new ArrayMap<>(); - - long curTime = System.currentTimeMillis(); - PermissionUsages usages = new PermissionUsages(this); - long filterTimeBeginMillis = Math.max(System.currentTimeMillis() - numMillis, 0); - usages.load(null, null, filterTimeBeginMillis, Long.MAX_VALUE, - PermissionUsages.USAGE_FLAG_LAST | PermissionUsages.USAGE_FLAG_HISTORICAL, null, - false, false, null, true); - - List<AppPermissionUsage> appPermissionUsages = usages.getUsages(); - int numApps = appPermissionUsages.size(); - for (int appNum = 0; appNum < numApps; appNum++) { - AppPermissionUsage appPermissionUsage = appPermissionUsages.get(appNum); - - List<GroupUsage> appGroups = appPermissionUsage.getGroupUsages(); - int numGroups = appGroups.size(); - for (int groupNum = 0; groupNum < numGroups; groupNum++) { - GroupUsage groupUsage = appGroups.get(groupNum); - - if (groupUsage.getLastAccessTime() < filterTimeBeginMillis) { - continue; - } - if (!shouldShowPermission(this, groupUsage.getGroup())) { - continue; - } - if (!countSystem && !Utils.isGroupOrBgGroupUserSensitive(groupUsage.getGroup())) { - continue; - } - - String groupName = groupUsage.getGroup().getName(); - Integer numUsers = groupUsers.get(groupName); - if (numUsers == null) { - groupUsers.put(groupName, 1); - } else { - groupUsers.put(groupName, numUsers + 1); - } - } - } - - List<RuntimePermissionUsageInfo> users = new ArrayList<>(); - int numGroups = groupUsers.size(); - for (int groupNum = 0; groupNum < numGroups; groupNum++) { - users.add(new RuntimePermissionUsageInfo(groupUsers.keyAt(groupNum), - groupUsers.valueAt(groupNum))); - } - return users; + return Collections.emptyList(); } @Override diff --git a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java index 6dd32799..56dc4957 100644 --- a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java +++ b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java @@ -33,9 +33,7 @@ import com.android.packageinstaller.permission.ui.auto.AutoAppPermissionsFragmen import com.android.packageinstaller.permission.ui.auto.AutoManageStandardPermissionsFragment; import com.android.packageinstaller.permission.ui.auto.AutoPermissionAppsFragment; import com.android.packageinstaller.permission.ui.handheld.ManageStandardPermissionsFragment; -import com.android.packageinstaller.permission.ui.handheld.PermissionUsageFragment; import com.android.packageinstaller.permission.ui.wear.AppPermissionsFragmentWear; -import com.android.packageinstaller.permission.utils.Utils; import com.android.permissioncontroller.R; public final class ManagePermissionsActivity extends FragmentActivity { @@ -78,35 +76,9 @@ public final class ManagePermissionsActivity extends FragmentActivity { } break; - case Intent.ACTION_REVIEW_PERMISSION_USAGE: { - if (!Utils.isPermissionsHubEnabled()) { - finish(); - return; - } - - permissionName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_NAME); - String groupName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME); - long numMillis = getIntent().getLongExtra(Intent.EXTRA_DURATION_MILLIS, - Long.MAX_VALUE); - - if (permissionName != null) { - String permGroupName = Utils.getGroupOfPlatformPermission(permissionName); - if (permGroupName == null) { - Log.w(LOG_TAG, "Invalid platform permission: " + permissionName); - } - if (groupName != null && !groupName.equals(permGroupName)) { - Log.i(LOG_TAG, - "Inconsistent EXTRA_PERMISSION_NAME / EXTRA_PERMISSION_GROUP_NAME"); - finish(); - return; - } - if (groupName == null) { - groupName = permGroupName; - } - } - - androidXFragment = PermissionUsageFragment.newInstance(groupName, numMillis); - } break; + case Intent.ACTION_REVIEW_PERMISSION_USAGE: + finish(); + return; case Intent.ACTION_MANAGE_APP_PERMISSIONS: { String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); diff --git a/src/com/android/packageinstaller/permission/ui/ReviewOngoingUsageActivity.java b/src/com/android/packageinstaller/permission/ui/ReviewOngoingUsageActivity.java index 5568216e..f81c1d1b 100644 --- a/src/com/android/packageinstaller/permission/ui/ReviewOngoingUsageActivity.java +++ b/src/com/android/packageinstaller/permission/ui/ReviewOngoingUsageActivity.java @@ -16,57 +16,16 @@ package com.android.packageinstaller.permission.ui; -import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; - -import android.content.Intent; import android.os.Bundle; -import android.view.MenuItem; -import androidx.annotation.NonNull; import androidx.fragment.app.FragmentActivity; -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.permission.ui.auto.ReviewOngoingUsageAutoFragment; -import com.android.packageinstaller.permission.ui.handheld.ReviewOngoingUsageFragment; - -/** - * A dialog listing the currently uses of camera, microphone, and location. - */ public final class ReviewOngoingUsageActivity extends FragmentActivity { - // Number of milliseconds in the past to look for accesses if nothing was specified. - private static final long DEFAULT_MILLIS = 5000; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - - long numMillis = getIntent().getLongExtra(Intent.EXTRA_DURATION_MILLIS, DEFAULT_MILLIS); - if (DeviceUtils.isAuto(this)) { - getSupportFragmentManager().beginTransaction().replace(android.R.id.content, - ReviewOngoingUsageAutoFragment.newInstance(numMillis)).commit(); - } else { - getSupportFragmentManager().beginTransaction().replace(android.R.id.content, - ReviewOngoingUsageFragment.newInstance(numMillis)).commit(); - } - } - - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - // in automotive mode, there's no system wide back button, so need to add that - if (DeviceUtils.isAuto(this)) { - onBackPressed(); - } else { - finish(); - } - return true; - default: - return super.onOptionsItemSelected(item); - } + finish(); + return; } } diff --git a/src/com/android/packageinstaller/permission/ui/auto/AutoAppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/auto/AutoAppPermissionsFragment.java index aac7faf6..010fa7ad 100644 --- a/src/com/android/packageinstaller/permission/ui/auto/AutoAppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/auto/AutoAppPermissionsFragment.java @@ -23,7 +23,6 @@ import android.content.pm.PackageInfo; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; -import android.text.TextUtils; import android.widget.Toast; import androidx.annotation.NonNull; @@ -36,7 +35,6 @@ import androidx.preference.PreferenceScreen; import com.android.packageinstaller.auto.AutoSettingsFrameFragment; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.model.PermissionUsages; import com.android.packageinstaller.permission.ui.AppPermissionActivity; import com.android.packageinstaller.permission.utils.Utils; import com.android.permissioncontroller.R; @@ -247,7 +245,6 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment { 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); @@ -261,37 +258,6 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment { return preference; } - private String getPreferenceSummary(AppPermissionGroup group) { - String groupSummary = getGroupSummary(group); - - if (Utils.isModernPermissionGroup(group.getName()) && Utils.shouldShowPermissionUsage( - group.getName())) { - String lastAccessStr = Utils.getAbsoluteLastUsageString(getContext(), - PermissionUsages.loadLastGroupUsage(getContext(), group)); - if (lastAccessStr != null) { - if (group.areRuntimePermissionsGranted()) { - return getContext().getString(R.string.app_permission_most_recent_summary, - lastAccessStr); - } else { - return getContext().getString( - R.string.app_permission_most_recent_denied_summary, lastAccessStr); - } - } else { - if (TextUtils.isEmpty(groupSummary) && Utils.isPermissionsHubEnabled()) { - if (group.areRuntimePermissionsGranted()) { - return getContext().getString( - R.string.app_permission_never_accessed_summary); - } else { - return getContext().getString( - R.string.app_permission_never_accessed_denied_summary); - } - } - } - } - - return groupSummary; - } - private String getGroupSummary(AppPermissionGroup group) { if (group.hasPermissionWithBackgroundMode() && group.areRuntimePermissionsGranted()) { AppPermissionGroup backgroundGroup = group.getBackgroundPermissions(); diff --git a/src/com/android/packageinstaller/permission/ui/auto/AutoPermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/auto/AutoPermissionAppsFragment.java index d4242385..9d310006 100644 --- a/src/com/android/packageinstaller/permission/ui/auto/AutoPermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/auto/AutoPermissionAppsFragment.java @@ -33,7 +33,6 @@ import com.android.packageinstaller.auto.AutoSettingsFrameFragment; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.PermissionApps; import com.android.packageinstaller.permission.model.PermissionApps.Callback; -import com.android.packageinstaller.permission.model.PermissionUsages; import com.android.packageinstaller.permission.ui.handheld.PermissionAppsFragment; import com.android.packageinstaller.permission.ui.handheld.PermissionControlPreference; import com.android.packageinstaller.permission.utils.Utils; @@ -263,10 +262,6 @@ public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implem } if (existingPref != null) { - if (existingPref instanceof PermissionControlPreference) { - setPreferenceSummary(group, (PermissionControlPreference) existingPref, - category != denied, context); - } category.addPreference(existingPref); continue; } @@ -278,7 +273,6 @@ public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implem pref.setTitle(Utils.getFullAppLabel(app.getAppInfo(), context)); pref.setEllipsizeEnd(); pref.useSmallerIcon(); - setPreferenceSummary(group, pref, category != denied, context); category.addPreference(pref); } @@ -307,32 +301,4 @@ public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implem setShowSystemAppsToggle(); setLoading(false); } - - private void setPreferenceSummary(AppPermissionGroup group, PermissionControlPreference pref, - boolean allowed, Context context) { - if (!Utils.isModernPermissionGroup(group.getName())) { - return; - } - if (!Utils.shouldShowPermissionUsage(group.getName())) { - return; - } - String lastAccessStr = Utils.getAbsoluteLastUsageString(context, - PermissionUsages.loadLastGroupUsage(context, group)); - if (lastAccessStr != null) { - if (allowed) { - pref.setSummary(context.getString(R.string.app_permission_most_recent_summary, - lastAccessStr)); - } else { - pref.setSummary( - context.getString(R.string.app_permission_most_recent_denied_summary, - lastAccessStr)); - } - } else if (Utils.isPermissionsHubEnabled()) { - if (allowed) { - pref.setSummary(R.string.app_permission_never_accessed_summary); - } else { - pref.setSummary(R.string.app_permission_never_accessed_denied_summary); - } - } - } } diff --git a/src/com/android/packageinstaller/permission/ui/auto/ReviewOngoingUsageAutoFragment.java b/src/com/android/packageinstaller/permission/ui/auto/ReviewOngoingUsageAutoFragment.java deleted file mode 100644 index beeed38b..00000000 --- a/src/com/android/packageinstaller/permission/ui/auto/ReviewOngoingUsageAutoFragment.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.packageinstaller.permission.ui.auto; - -import android.app.AlertDialog; -import android.content.Intent; -import android.os.Bundle; - -import com.android.packageinstaller.permission.ui.handheld.ReviewOngoingUsageFragment; - -/** - * A dialog listing the currently uses of camera, microphone, and location. - */ -public class ReviewOngoingUsageAutoFragment extends ReviewOngoingUsageFragment { - - /** - * @return A new {@link ReviewOngoingUsageAutoFragment} - */ - public static ReviewOngoingUsageAutoFragment newInstance(long numMillis) { - ReviewOngoingUsageAutoFragment fragment = new ReviewOngoingUsageAutoFragment(); - Bundle arguments = new Bundle(); - arguments.putLong(Intent.EXTRA_DURATION_MILLIS, numMillis); - fragment.setArguments(arguments); - return fragment; - } - - @Override - protected void setNeutralButton(AlertDialog.Builder builder) { - // do nothing - } -} diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionFragment.java index d314bd73..4ee0abe4 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionFragment.java @@ -18,7 +18,6 @@ package com.android.packageinstaller.permission.ui.handheld; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.Manifest; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; @@ -54,7 +53,6 @@ import androidx.fragment.app.Fragment; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.model.PermissionUsages; import com.android.packageinstaller.permission.ui.AppPermissionActivity; import com.android.packageinstaller.permission.utils.LocationUtils; import com.android.packageinstaller.permission.utils.PackageRemovalMonitor; @@ -195,19 +193,7 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { ((TextView) root.requireViewById(R.id.permission_message)).setText( context.getString(R.string.app_permission_header, mGroup.getFullLabel())); - if (!Utils.isPermissionsHubEnabled()) { - root.requireViewById(R.id.usage_summary).setVisibility(View.GONE); - } else if (Utils.isModernPermissionGroup(mGroup.getName())) { - if (!Utils.shouldShowPermissionUsage(mGroup.getName())) { - ((TextView) root.requireViewById(R.id.usage_summary)).setText( - context.getString(R.string.app_permission_footer_not_available)); - } else { - ((TextView) root.requireViewById(R.id.usage_summary)).setText( - getUsageSummary(context, appLabel)); - } - } else { - root.requireViewById(R.id.usage_summary).setVisibility(View.GONE); - } + root.requireViewById(R.id.usage_summary).setVisibility(View.GONE); TextView footer1Link = root.requireViewById(R.id.footer_link_1); footer1Link.setText(context.getString(R.string.app_permission_footer_app_permissions_link, @@ -248,93 +234,6 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { return root; } - private @NonNull String getUsageSummary(@NonNull Context context, @NonNull String appLabel) { - String timeDiffStr = Utils.getRelativeLastUsageString(context, - PermissionUsages.loadLastGroupUsage(context, mGroup)); - int strResId; - if (timeDiffStr == null) { - switch (mGroup.getName()) { - case Manifest.permission_group.ACTIVITY_RECOGNITION: - strResId = R.string.app_permission_footer_no_usages_activity_recognition; - break; - case Manifest.permission_group.CALENDAR: - strResId = R.string.app_permission_footer_no_usages_calendar; - break; - case Manifest.permission_group.CALL_LOG: - strResId = R.string.app_permission_footer_no_usages_call_log; - break; - case Manifest.permission_group.CAMERA: - strResId = R.string.app_permission_footer_no_usages_camera; - break; - case Manifest.permission_group.CONTACTS: - strResId = R.string.app_permission_footer_no_usages_contacts; - break; - case Manifest.permission_group.LOCATION: - strResId = R.string.app_permission_footer_no_usages_location; - break; - case Manifest.permission_group.MICROPHONE: - strResId = R.string.app_permission_footer_no_usages_microphone; - break; - case Manifest.permission_group.PHONE: - strResId = R.string.app_permission_footer_no_usages_phone; - break; - case Manifest.permission_group.SENSORS: - strResId = R.string.app_permission_footer_no_usages_sensors; - break; - case Manifest.permission_group.SMS: - strResId = R.string.app_permission_footer_no_usages_sms; - break; - case Manifest.permission_group.STORAGE: - strResId = R.string.app_permission_footer_no_usages_storage; - break; - default: - return context.getString(R.string.app_permission_footer_no_usages_generic, - appLabel, mGroup.getLabel().toString().toLowerCase()); - } - return context.getString(strResId, appLabel); - } else { - switch (mGroup.getName()) { - case Manifest.permission_group.ACTIVITY_RECOGNITION: - strResId = R.string.app_permission_footer_usage_summary_activity_recognition; - break; - case Manifest.permission_group.CALENDAR: - strResId = R.string.app_permission_footer_usage_summary_calendar; - break; - case Manifest.permission_group.CALL_LOG: - strResId = R.string.app_permission_footer_usage_summary_call_log; - break; - case Manifest.permission_group.CAMERA: - strResId = R.string.app_permission_footer_usage_summary_camera; - break; - case Manifest.permission_group.CONTACTS: - strResId = R.string.app_permission_footer_usage_summary_contacts; - break; - case Manifest.permission_group.LOCATION: - strResId = R.string.app_permission_footer_usage_summary_location; - break; - case Manifest.permission_group.MICROPHONE: - strResId = R.string.app_permission_footer_usage_summary_microphone; - break; - case Manifest.permission_group.PHONE: - strResId = R.string.app_permission_footer_usage_summary_phone; - break; - case Manifest.permission_group.SENSORS: - strResId = R.string.app_permission_footer_usage_summary_sensors; - break; - case Manifest.permission_group.SMS: - strResId = R.string.app_permission_footer_usage_summary_sms; - break; - case Manifest.permission_group.STORAGE: - strResId = R.string.app_permission_footer_usage_summary_storage; - break; - default: - return context.getString(R.string.app_permission_footer_usage_summary_generic, - appLabel, mGroup.getLabel().toString().toLowerCase(), timeDiffStr); - } - return context.getString(strResId, appLabel, timeDiffStr); - } - } - @Override public void onStart() { super.onStart(); diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java index 26cebb51..1fe8d0f3 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java @@ -43,7 +43,6 @@ import androidx.preference.PreferenceScreen; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.model.PermissionUsages; import com.android.packageinstaller.permission.utils.Utils; import com.android.permissioncontroller.R; import com.android.settingslib.HelpUtils; @@ -231,34 +230,7 @@ public final class AppPermissionsFragment extends SettingsWithLargeHeader { preference.setIcon(Utils.applyTint(context, icon, android.R.attr.colorControlNormal)); preference.setTitle(group.getFullLabel()); - if (Utils.isModernPermissionGroup(group.getName()) && Utils.shouldShowPermissionUsage( - group.getName())) { - String lastAccessStr = Utils.getAbsoluteLastUsageString(context, - PermissionUsages.loadLastGroupUsage(context, group)); - if (lastAccessStr != null) { - if (group.areRuntimePermissionsGranted()) { - preference.setSummary( - context.getString(R.string.app_permission_most_recent_summary, - lastAccessStr)); - } else { - preference.setSummary(context.getString( - R.string.app_permission_most_recent_denied_summary, lastAccessStr)); - } - } else { - preference.setGroupSummary(group); - if (preference.getSummary().length() == 0 && Utils.isPermissionsHubEnabled()) { - if (group.areRuntimePermissionsGranted()) { - preference.setSummary(context.getString( - R.string.app_permission_never_accessed_summary)); - } else { - preference.setSummary(context.getString( - R.string.app_permission_never_accessed_denied_summary)); - } - } - } - } else { - preference.setGroupSummary(group); - } + preference.setGroupSummary(group); if (isPlatform) { PreferenceCategory category = diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ExpandablePreferenceGroup.java b/src/com/android/packageinstaller/permission/ui/handheld/ExpandablePreferenceGroup.java deleted file mode 100644 index 49a2d5f6..00000000 --- a/src/com/android/packageinstaller/permission/ui/handheld/ExpandablePreferenceGroup.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.packageinstaller.permission.ui.handheld; - -import android.content.Context; -import android.text.TextUtils; -import android.util.Pair; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.preference.Preference; -import androidx.preference.PreferenceGroup; -import androidx.preference.PreferenceViewHolder; - -import com.android.permissioncontroller.R; - -import java.util.ArrayList; -import java.util.List; - -/** - * A preference group that expands/collapses its children when clicked. - */ -public class ExpandablePreferenceGroup extends PreferenceGroup { - private @NonNull Context mContext; - private @NonNull List<Preference> mPreferences; - private @NonNull List<Pair<Integer, CharSequence>> mSummaryIcons; - private boolean mExpanded; - - public ExpandablePreferenceGroup(@NonNull Context context) { - super(context, null); - - mContext = context; - mPreferences = new ArrayList<>(); - mSummaryIcons = new ArrayList<>(); - mExpanded = false; - - setLayoutResource(R.layout.preference_usage); - setWidgetLayoutResource(R.layout.image_view); - setOnPreferenceClickListener(preference -> { - if (!mExpanded) { - int numPreferences = mPreferences.size(); - for (int i = 0; i < numPreferences; i++) { - super.addPreference(mPreferences.get(i)); - } - } else { - removeAll(); - } - mExpanded = !mExpanded; - return true; - }); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - ImageView icon = (ImageView) holder.findViewById(android.R.id.icon); - int rightIconSize = mContext.getResources().getDimensionPixelSize( - R.dimen.secondary_app_icon_size); - icon.setMaxWidth(rightIconSize); - icon.setMaxHeight(rightIconSize); - - super.onBindViewHolder(holder); - - TextView summary = (TextView) holder.findViewById(android.R.id.summary); - summary.setMaxLines(1); - summary.setEllipsize(TextUtils.TruncateAt.END); - - ImageView rightImageView = holder.findViewById( - android.R.id.widget_frame).findViewById(R.id.icon); - if (mExpanded) { - rightImageView.setImageResource(R.drawable.ic_arrow_up); - } else { - rightImageView.setImageResource(R.drawable.ic_arrow_down); - } - - holder.setDividerAllowedAbove(false); - holder.setDividerAllowedBelow(false); - - holder.findViewById(R.id.title_widget_frame).setVisibility(View.GONE); - - ViewGroup summaryFrame = (ViewGroup) holder.findViewById(R.id.summary_widget_frame); - if (mSummaryIcons.isEmpty()) { - summaryFrame.setVisibility(View.GONE); - } else { - summaryFrame.removeAllViews(); - int numIcons = mSummaryIcons.size(); - for (int i = 0; i < numIcons; i++) { - LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class); - ViewGroup group = (ViewGroup) inflater.inflate(R.layout.title_summary_image_view, - null); - ImageView imageView = group.requireViewById(R.id.icon); - Pair<Integer, CharSequence> summaryIcons = mSummaryIcons.get(i); - imageView.setImageResource(summaryIcons.first); - if (summaryIcons.second != null) { - imageView.setContentDescription(summaryIcons.second); - } - summaryFrame.addView(group); - } - } - } - - @Override - public boolean addPreference(Preference preference) { - mPreferences.add(preference); - return true; - } - - /** - * Show the given icon next to this preference's summary. - * - * @param resId the resourceId of the drawable to use as the icon. - */ - public void addSummaryIcon(@DrawableRes int resId, @Nullable CharSequence contentDescription) { - mSummaryIcons.add(Pair.create(resId, contentDescription)); - } -} diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java index 70ea65a3..e1ceb46e 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java @@ -38,7 +38,6 @@ import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.PermissionApps; import com.android.packageinstaller.permission.model.PermissionApps.Callback; import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; -import com.android.packageinstaller.permission.model.PermissionUsages; import com.android.packageinstaller.permission.utils.Utils; import com.android.permissioncontroller.R; import com.android.settingslib.HelpUtils; @@ -293,10 +292,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem } if (existingPref != null) { - if (existingPref instanceof PermissionControlPreference) { - setPreferenceSummary(group, (PermissionControlPreference) existingPref, - category != denied, context); - } category.addPreference(existingPref); continue; } @@ -308,7 +303,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem pref.setTitle(Utils.getFullAppLabel(app.getAppInfo(), context)); pref.setEllipsizeEnd(); pref.useSmallerIcon(); - setPreferenceSummary(group, pref, category != denied, context); if (isSystemApp && isTelevision) { if (mExtraScreen == null) { @@ -376,18 +370,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem denied.addPreference(empty); } - if (!Utils.shouldShowPermissionUsage(mPermissionApps.getGroupName()) - && findPreference(KEY_FOOTER) == null) { - PreferenceCategory footer = new PreferenceCategory(context); - footer.setKey(KEY_FOOTER); - getPreferenceScreen().addPreference(footer); - Preference footerText = new Preference(context); - footerText.setSummary(context.getString(R.string.app_permission_footer_not_available)); - footerText.setIcon(R.drawable.ic_info_outline); - footerText.setSelectable(false); - footer.addPreference(footerText); - } - setLoading(false /* loading */, true /* animate */); if (mOnPermissionsLoadedListener != null) { @@ -395,35 +377,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem } } - private void setPreferenceSummary(AppPermissionGroup group, PermissionControlPreference pref, - boolean allowed, Context context) { - if (!Utils.isModernPermissionGroup(group.getName())) { - return; - } - if (!Utils.shouldShowPermissionUsage(group.getName())) { - return; - } - String lastAccessStr = Utils.getAbsoluteLastUsageString(context, - PermissionUsages.loadLastGroupUsage(context, group)); - if (lastAccessStr != null) { - if (allowed) { - pref.setSummary(context.getString(R.string.app_permission_most_recent_summary, - lastAccessStr)); - } else { - pref.setSummary( - context.getString(R.string.app_permission_most_recent_denied_summary, - lastAccessStr)); - } - } else if (Utils.isPermissionsHubEnabled()) { - if (allowed) { - pref.setSummary(context.getString(R.string.app_permission_never_accessed_summary)); - } else { - pref.setSummary( - context.getString(R.string.app_permission_never_accessed_denied_summary)); - } - } - } - public static class SystemAppsFragment extends SettingsWithLargeHeader implements Callback { PermissionAppsFragment mOuterFragment; diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionControlPreference.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionControlPreference.java index 362358b4..fa8321ca 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/PermissionControlPreference.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionControlPreference.java @@ -32,7 +32,6 @@ import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissionUsage.GroupUsage; import com.android.packageinstaller.permission.ui.AppPermissionActivity; import com.android.permissioncontroller.R; @@ -116,22 +115,6 @@ public class PermissionControlPreference extends Preference { } /** - * Sets this preference's summary based on its permission usage. - * - * @param groupUsage the usage information - * @param accessTimeStr the string representing the last access time - */ - public void setUsageSummary(@NonNull GroupUsage groupUsage, @NonNull String accessTimeStr) { - if (groupUsage.getLastAccessForegroundTime() >= groupUsage.getLastAccessBackgroundTime()) { - setSummary(mContext.getString(R.string.permission_usage_summary_foreground, - accessTimeStr)); - } else { - setSummary(mContext.getString(R.string.permission_usage_summary_background, - accessTimeStr)); - } - } - - /** * Sets this preference to show the given icons to the left of its title. * * @param titleIcons the icons to show. diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java deleted file mode 100644 index 3a302ad0..00000000 --- a/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java +++ /dev/null @@ -1,1056 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.packageinstaller.permission.ui.handheld; - -import static android.Manifest.permission_group.CAMERA; -import static android.Manifest.permission_group.LOCATION; -import static android.Manifest.permission_group.MICROPHONE; - -import static java.lang.annotation.RetentionPolicy.SOURCE; -import static java.util.concurrent.TimeUnit.DAYS; -import static java.util.concurrent.TimeUnit.HOURS; -import static java.util.concurrent.TimeUnit.MINUTES; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Log; -import android.util.Pair; -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.RadioButton; -import android.widget.TextView; - -import androidx.annotation.IntDef; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceScreen; - -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissionUsage; -import com.android.packageinstaller.permission.model.AppPermissionUsage.GroupUsage; -import com.android.packageinstaller.permission.model.PermissionApps; -import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; -import com.android.packageinstaller.permission.model.PermissionUsages; -import com.android.packageinstaller.permission.ui.AdjustUserSensitiveActivity; -import com.android.packageinstaller.permission.utils.Utils; -import com.android.permissioncontroller.R; -import com.android.settingslib.HelpUtils; -import com.android.settingslib.widget.ActionBarShadowController; -import com.android.settingslib.widget.BarChartInfo; -import com.android.settingslib.widget.BarChartPreference; -import com.android.settingslib.widget.BarViewInfo; - -import java.lang.annotation.Retention; -import java.text.Collator; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -/** - * Show the usage of all apps of all permission groups. - * - * <p>Shows a filterable list of app usage of permission groups, each of which links to - * AppPermissionsFragment. - */ -public class PermissionUsageFragment extends SettingsWithLargeHeader implements - PermissionUsages.PermissionsUsagesChangeCallback { - private static final String LOG_TAG = "PermissionUsageFragment"; - - @Retention(SOURCE) - @IntDef(value = {SORT_RECENT, SORT_RECENT_APPS}) - @interface SortOption {} - static final int SORT_RECENT = 1; - static final int SORT_RECENT_APPS = 2; - - private static final int MENU_SORT_BY_APP = MENU_HIDE_SYSTEM + 1; - private static final int MENU_SORT_BY_TIME = MENU_HIDE_SYSTEM + 2; - private static final int MENU_FILTER_BY_PERMISSIONS = MENU_HIDE_SYSTEM + 3; - private static final int MENU_FILTER_BY_TIME = MENU_HIDE_SYSTEM + 4; - private static final int MENU_REFRESH = MENU_HIDE_SYSTEM + 5; - private static final int MENU_ADJUST_USER_SENSITIVE = MENU_HIDE_SYSTEM + 6; - - private static final String KEY_SHOW_SYSTEM_PREFS = "_show_system"; - private static final String SHOW_SYSTEM_KEY = PermissionUsageFragment.class.getName() - + KEY_SHOW_SYSTEM_PREFS; - private static final String KEY_PERM_NAME = "_perm_name"; - private static final String PERM_NAME_KEY = PermissionUsageFragment.class.getName() - + KEY_PERM_NAME; - private static final String KEY_TIME_INDEX = "_time_index"; - private static final String TIME_INDEX_KEY = PermissionUsageFragment.class.getName() - + KEY_TIME_INDEX; - private static final String KEY_SORT = "_sort"; - private static final String SORT_KEY = PermissionUsageFragment.class.getName() - + KEY_SORT; - - /** - * The maximum number of columns shown in the bar chart. - */ - private static final int MAXIMUM_NUM_BARS = 4; - - private @NonNull PermissionUsages mPermissionUsages; - private @Nullable List<AppPermissionUsage> mAppPermissionUsages = new ArrayList<>(); - - private Collator mCollator; - - private @NonNull List<TimeFilterItem> mFilterTimes; - private int mFilterTimeIndex; - private String mFilterGroup; - private @SortOption int mSort; - - private boolean mShowSystem; - private boolean mHasSystemApps; - private MenuItem mShowSystemMenu; - private MenuItem mHideSystemMenu; - private MenuItem mSortByApp; - private MenuItem mSortByTime; - - private ArrayMap<String, Integer> mGroupAppCounts = new ArrayMap<>(); - - private boolean mFinishedInitialLoad; - - /** - * @return A new fragment - */ - public static @NonNull PermissionUsageFragment newInstance(@Nullable String groupName, - long numMillis) { - PermissionUsageFragment fragment = new PermissionUsageFragment(); - Bundle arguments = new Bundle(); - if (groupName != null) { - arguments.putString(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName); - } - arguments.putLong(Intent.EXTRA_DURATION_MILLIS, numMillis); - fragment.setArguments(arguments); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mFinishedInitialLoad = false; - mSort = SORT_RECENT_APPS; - mFilterGroup = null; - initializeTimeFilter(); - if (savedInstanceState != null) { - mShowSystem = savedInstanceState.getBoolean(SHOW_SYSTEM_KEY); - mFilterGroup = savedInstanceState.getString(PERM_NAME_KEY); - mFilterTimeIndex = savedInstanceState.getInt(TIME_INDEX_KEY); - mSort = savedInstanceState.getInt(SORT_KEY); - } - - setLoading(true, false); - setHasOptionsMenu(true); - ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - - if (mFilterGroup == null) { - mFilterGroup = getArguments().getString(Intent.EXTRA_PERMISSION_GROUP_NAME); - } - - Context context = getPreferenceManager().getContext(); - mCollator = Collator.getInstance( - context.getResources().getConfiguration().getLocales().get(0)); - mPermissionUsages = new PermissionUsages(context); - - reloadData(); - } - - @Override - public void onStart() { - super.onStart(); - getActivity().setTitle(R.string.permission_usage_title); - } - - /** - * Initialize the time filter to show the smallest entry greater than the time passed in as an - * argument. If nothing is passed, this simply initializes the possible values. - */ - private void initializeTimeFilter() { - Context context = getPreferenceManager().getContext(); - mFilterTimes = new ArrayList<>(); - mFilterTimes.add(new TimeFilterItem(Long.MAX_VALUE, - context.getString(R.string.permission_usage_any_time), - R.string.permission_usage_list_title_any_time, - R.string.permission_usage_bar_chart_title_any_time)); - mFilterTimes.add(new TimeFilterItem(DAYS.toMillis(7), - context.getString(R.string.permission_usage_last_7_days), - R.string.permission_usage_list_title_last_7_days, - R.string.permission_usage_bar_chart_title_last_7_days)); - mFilterTimes.add(new TimeFilterItem(DAYS.toMillis(1), - context.getString(R.string.permission_usage_last_day), - R.string.permission_usage_list_title_last_day, - R.string.permission_usage_bar_chart_title_last_day)); - mFilterTimes.add(new TimeFilterItem(HOURS.toMillis(1), - context.getString(R.string.permission_usage_last_hour), - R.string.permission_usage_list_title_last_hour, - R.string.permission_usage_bar_chart_title_last_hour)); - mFilterTimes.add(new TimeFilterItem(MINUTES.toMillis(15), - context.getString(R.string.permission_usage_last_15_minutes), - R.string.permission_usage_list_title_last_15_minutes, - R.string.permission_usage_bar_chart_title_last_15_minutes)); - mFilterTimes.add(new TimeFilterItem(MINUTES.toMillis(1), - context.getString(R.string.permission_usage_last_minute), - R.string.permission_usage_list_title_last_minute, - R.string.permission_usage_bar_chart_title_last_minute)); - - long numMillis = getArguments().getLong(Intent.EXTRA_DURATION_MILLIS); - long supremum = Long.MAX_VALUE; - int supremumIndex = -1; - int numTimes = mFilterTimes.size(); - for (int i = 0; i < numTimes; i++) { - long curTime = mFilterTimes.get(i).getTime(); - if (curTime >= numMillis && curTime <= supremum) { - supremum = curTime; - supremumIndex = i; - } - } - if (supremumIndex != -1) { - mFilterTimeIndex = supremumIndex; - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(SHOW_SYSTEM_KEY, mShowSystem); - outState.putString(PERM_NAME_KEY, mFilterGroup); - outState.putInt(TIME_INDEX_KEY, mFilterTimeIndex); - outState.putInt(SORT_KEY, mSort); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - mSortByApp = menu.add(Menu.NONE, MENU_SORT_BY_APP, Menu.NONE, R.string.sort_by_app); - mSortByTime = menu.add(Menu.NONE, MENU_SORT_BY_TIME, Menu.NONE, R.string.sort_by_time); - menu.add(Menu.NONE, MENU_FILTER_BY_PERMISSIONS, Menu.NONE, R.string.filter_by_permissions); - menu.add(Menu.NONE, MENU_FILTER_BY_TIME, Menu.NONE, R.string.filter_by_time); - if (mHasSystemApps) { - mShowSystemMenu = menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE, - R.string.menu_show_system); - mHideSystemMenu = menu.add(Menu.NONE, MENU_HIDE_SYSTEM, Menu.NONE, - R.string.menu_hide_system); - } - - menu.add(Menu.NONE, MENU_ADJUST_USER_SENSITIVE, Menu.NONE, - R.string.menu_adjust_user_sensitive); - - HelpUtils.prepareHelpMenuItem(getActivity(), menu, R.string.help_permission_usage, - getClass().getName()); - MenuItem refresh = menu.add(Menu.NONE, MENU_REFRESH, Menu.NONE, - R.string.permission_usage_refresh); - refresh.setIcon(R.drawable.ic_refresh); - refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - updateMenu(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getActivity().finish(); - return true; - case MENU_SORT_BY_APP: - mSort = SORT_RECENT_APPS; - updateUI(); - updateMenu(); - break; - case MENU_SORT_BY_TIME: - mSort = SORT_RECENT; - updateUI(); - updateMenu(); - break; - case MENU_FILTER_BY_PERMISSIONS: - showPermissionFilterDialog(); - break; - case MENU_FILTER_BY_TIME: - showTimeFilterDialog(); - break; - case MENU_SHOW_SYSTEM: - case MENU_HIDE_SYSTEM: - mShowSystem = item.getItemId() == MENU_SHOW_SYSTEM; - // We already loaded all data, so don't reload - updateUI(); - updateMenu(); - break; - case MENU_REFRESH: - reloadData(); - break; - case MENU_ADJUST_USER_SENSITIVE: - getActivity().startActivity( - new Intent(getContext(), AdjustUserSensitiveActivity.class)); - break; - } - return super.onOptionsItemSelected(item); - } - - private void updateMenu() { - if (mHasSystemApps) { - mShowSystemMenu.setVisible(!mShowSystem); - mHideSystemMenu.setVisible(mShowSystem); - } - mSortByApp.setVisible(mSort != SORT_RECENT_APPS); - mSortByTime.setVisible(mSort != SORT_RECENT); - } - - @Override - public void onPermissionUsagesChanged() { - if (!Utils.isPermissionsHubEnabled()) { - setLoading(false, true); - return; - } - if (mPermissionUsages.getUsages().isEmpty()) { - return; - } - mAppPermissionUsages = new ArrayList<>(mPermissionUsages.getUsages()); - - // Ensure the group name is valid. - if (getGroup(mFilterGroup) == null) { - mFilterGroup = null; - } - - updateUI(); - } - - @Override - public int getEmptyViewString() { - return R.string.no_permission_usages; - } - - private void updateUI() { - if (mAppPermissionUsages.isEmpty() || getActivity() == null) { - return; - } - Context context = getActivity(); - - PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(context); - setPreferenceScreen(screen); - } - screen.removeAll(); - - boolean seenSystemApp = false; - - final TimeFilterItem timeFilterItem = mFilterTimes.get(mFilterTimeIndex); - long curTime = System.currentTimeMillis(); - long startTime = Math.max(timeFilterItem == null ? 0 : (curTime - timeFilterItem.getTime()), - Instant.EPOCH.toEpochMilli()); - - List<Pair<AppPermissionUsage, GroupUsage>> usages = new ArrayList<>(); - mGroupAppCounts.clear(); - ArrayList<PermissionApp> permApps = new ArrayList<>(); - int numApps = mAppPermissionUsages.size(); - for (int appNum = 0; appNum < numApps; appNum++) { - AppPermissionUsage appUsage = mAppPermissionUsages.get(appNum); - boolean used = false; - List<GroupUsage> appGroups = appUsage.getGroupUsages(); - int numGroups = appGroups.size(); - for (int groupNum = 0; groupNum < numGroups; groupNum++) { - GroupUsage groupUsage = appGroups.get(groupNum); - long lastAccessTime = groupUsage.getLastAccessTime(); - - if (lastAccessTime == 0) { - Log.w(LOG_TAG, - "Unexpected access time of 0 for " + appUsage.getApp().getKey() + " " - + groupUsage.getGroup().getName()); - continue; - } - if (lastAccessTime < startTime) { - continue; - } - final boolean isSystemApp = !Utils.isGroupOrBgGroupUserSensitive( - groupUsage.getGroup()); - seenSystemApp = seenSystemApp || isSystemApp; - if (isSystemApp && !mShowSystem) { - continue; - } - - used = true; - addGroupUser(groupUsage.getGroup().getName()); - - // Filter out usages that aren't of the filtered permission group. - // We do this after we call addGroupUser so we compute the correct usage counts - // for the permission filter dialog but before we add the usage to our list. - if (mFilterGroup != null && !mFilterGroup.equals(groupUsage.getGroup().getName())) { - continue; - } - - usages.add(Pair.create(appUsage, appGroups.get(groupNum))); - } - if (used) { - permApps.add(appUsage.getApp()); - addGroupUser(null); - } - } - - if (mHasSystemApps != seenSystemApp) { - mHasSystemApps = seenSystemApp; - getActivity().invalidateOptionsMenu(); - } - - // Update header. - if (mFilterGroup == null) { - screen.addPreference(createBarChart(usages, timeFilterItem, context)); - hideHeader(); - } else { - AppPermissionGroup group = getGroup(mFilterGroup); - if (group != null) { - setHeader(Utils.applyTint(context, context.getDrawable(group.getIconResId()), - android.R.attr.colorControlNormal), - context.getString(R.string.app_permission_usage_filter_label, - group.getLabel()), null, null, true); - setSummary(context.getString(R.string.app_permission_usage_remove_filter), v -> { - onPermissionGroupSelected(null); - }); - } - } - - // Add the preference header. - PreferenceCategory category = new PreferenceCategory(context); - screen.addPreference(category); - if (timeFilterItem != null) { - category.setTitle(timeFilterItem.getListTitleRes()); - } - - // Sort the apps. - if (mSort == SORT_RECENT) { - usages.sort(PermissionUsageFragment::compareAccessRecency); - } else if (mSort == SORT_RECENT_APPS) { - if (mFilterGroup == null) { - usages.sort(PermissionUsageFragment::compareAccessAppRecency); - } else { - usages.sort(PermissionUsageFragment::compareAccessTime); - } - } else { - Log.w(LOG_TAG, "Unexpected sort option: " + mSort); - } - - // If there are no entries, don't show anything. - if (usages.isEmpty()) { - screen.removeAll(); - } - - new PermissionApps.AppDataLoader(context, () -> { - ExpandablePreferenceGroup parent = null; - AppPermissionUsage lastAppPermissionUsage = null; - String lastAccessTimeString = null; - List<CharSequence> groups = new ArrayList<>(); - - final int numUsages = usages.size(); - for (int usageNum = 0; usageNum < numUsages; usageNum++) { - final Pair<AppPermissionUsage, GroupUsage> usage = usages.get(usageNum); - AppPermissionUsage appPermissionUsage = usage.first; - GroupUsage groupUsage = usage.second; - - String accessTimeString = Utils.getAbsoluteLastUsageString(context, groupUsage); - - if (lastAppPermissionUsage != appPermissionUsage || (mSort == SORT_RECENT - && !accessTimeString.equals(lastAccessTimeString))) { - setPermissionSummary(parent, groups); - // Add a "parent" entry for the app that will expand to the individual entries. - parent = createExpandablePreferenceGroup(context, appPermissionUsage, - mSort == SORT_RECENT ? accessTimeString : null); - category.addPreference(parent); - lastAppPermissionUsage = appPermissionUsage; - groups = new ArrayList<>(); - } - - parent.addPreference(createPermissionUsagePreference(context, appPermissionUsage, - groupUsage, accessTimeString)); - groups.add(groupUsage.getGroup().getLabel()); - lastAccessTimeString = accessTimeString; - } - - setPermissionSummary(parent, groups); - - setLoading(false, true); - mFinishedInitialLoad = true; - setProgressBarVisible(false); - mPermissionUsages.stopLoader(getActivity().getLoaderManager()); - }).execute(permApps.toArray(new PermissionApps.PermissionApp[permApps.size()])); - } - - private void addGroupUser(String app) { - Integer count = mGroupAppCounts.get(app); - if (count == null) { - mGroupAppCounts.put(app, 1); - } else { - mGroupAppCounts.put(app, count + 1); - } - } - - private void setPermissionSummary(@NonNull ExpandablePreferenceGroup pref, - @NonNull List<CharSequence> groups) { - if (pref == null) { - return; - } - StringBuilder sb = new StringBuilder(); - int numGroups = groups.size(); - for (int i = 0; i < numGroups; i++) { - sb.append(groups.get(i)); - if (i < numGroups - 1) { - sb.append(getString(R.string.item_separator)); - } - } - pref.setSummary(sb.toString()); - } - - /** - * Reloads the data to show. - */ - private void reloadData() { - final TimeFilterItem timeFilterItem = mFilterTimes.get(mFilterTimeIndex); - final long filterTimeBeginMillis = Math.max(System.currentTimeMillis() - - timeFilterItem.getTime(), Instant.EPOCH.toEpochMilli()); - mPermissionUsages.load(null /*filterPackageName*/, null /*filterPermissionGroups*/, - filterTimeBeginMillis, Long.MAX_VALUE, PermissionUsages.USAGE_FLAG_LAST - | PermissionUsages.USAGE_FLAG_HISTORICAL, getActivity().getLoaderManager(), - false /*getUiInfo*/, false /*getNonPlatformPermissions*/, this /*callback*/, - false /*sync*/); - if (mFinishedInitialLoad) { - setProgressBarVisible(true); - } - } - /** - * Create a bar chart showing the permissions that are used by the most apps. - * - * @param usages the usages - * @param timeFilterItem the time filter, or null if no filter is set - * @param context the context - * - * @return the Preference representing the bar chart - */ - private BarChartPreference createBarChart( - @NonNull List<Pair<AppPermissionUsage, GroupUsage>> usages, - @Nullable TimeFilterItem timeFilterItem, @NonNull Context context) { - ArrayList<AppPermissionGroup> groups = new ArrayList<>(); - ArrayMap<String, Integer> groupToAppCount = new ArrayMap<>(); - int usageCount = usages.size(); - for (int i = 0; i < usageCount; i++) { - Pair<AppPermissionUsage, GroupUsage> usage = usages.get(i); - GroupUsage groupUsage = usage.second; - Integer count = groupToAppCount.get(groupUsage.getGroup().getName()); - if (count == null) { - groups.add(groupUsage.getGroup()); - groupToAppCount.put(groupUsage.getGroup().getName(), 1); - } else { - groupToAppCount.put(groupUsage.getGroup().getName(), count + 1); - } - } - - groups.sort((x, y) -> { - String xName = x.getName(); - String yName = y.getName(); - int usageDiff = compareLong(groupToAppCount.get(xName), groupToAppCount.get(yName)); - if (usageDiff != 0) { - return usageDiff; - } - if (xName.equals(LOCATION)) { - return -1; - } else if (yName.equals(LOCATION)) { - return 1; - } else if (xName.equals(MICROPHONE)) { - return -1; - } else if (yName.equals(MICROPHONE)) { - return 1; - } else if (xName.equals(CAMERA)) { - return -1; - } else if (yName.equals(CAMERA)) { - return 1; - } - return x.getName().compareTo(y.getName()); - }); - - BarChartInfo.Builder builder = new BarChartInfo.Builder(); - if (timeFilterItem != null) { - builder.setTitle(timeFilterItem.getGraphTitleRes()); - } - - int numBarsToShow = Math.min(groups.size(), MAXIMUM_NUM_BARS); - for (int i = 0; i < numBarsToShow; i++) { - AppPermissionGroup group = groups.get(i); - int count = groupToAppCount.get(group.getName()); - Drawable icon = Utils.applyTint(context, - Utils.loadDrawable(context.getPackageManager(), group.getIconPkg(), - group.getIconResId()), android.R.attr.colorControlNormal); - BarViewInfo barViewInfo = new BarViewInfo(icon, count, group.getLabel(), - context.getResources().getQuantityString(R.plurals.permission_usage_bar_label, - count, count), group.getLabel()); - barViewInfo.setClickListener(v -> onPermissionGroupSelected(group.getName())); - builder.addBarViewInfo(barViewInfo); - } - - BarChartPreference barChart = new BarChartPreference(context, null); - barChart.initializeBarChart(builder.build()); - return barChart; - } - - /** - * Create an expandable preference group that can hold children. - * - * @param context the context - * @param appPermissionUsage the permission usage for an app - * - * @return the expandable preference group. - */ - private ExpandablePreferenceGroup createExpandablePreferenceGroup(@NonNull Context context, - @NonNull AppPermissionUsage appPermissionUsage, @Nullable String summaryString) { - ExpandablePreferenceGroup preference = new ExpandablePreferenceGroup(context); - preference.setTitle(appPermissionUsage.getApp().getLabel()); - preference.setIcon(appPermissionUsage.getApp().getIcon()); - if (summaryString != null) { - preference.setSummary(summaryString); - } - return preference; - } - - /** - * Create a preference representing an app's use of a permission - * - * @param context the context - * @param appPermissionUsage the permission usage for the app - * @param groupUsage the permission item to add - * @param accessTimeStr the string representing the access time - * - * @return the Preference - */ - private PermissionControlPreference createPermissionUsagePreference(@NonNull Context context, - @NonNull AppPermissionUsage appPermissionUsage, - @NonNull GroupUsage groupUsage, @NonNull String accessTimeStr) { - final PermissionControlPreference pref = new PermissionControlPreference(context, - groupUsage.getGroup(), PermissionUsageFragment.class.getName()); - - final AppPermissionGroup group = groupUsage.getGroup(); - pref.setTitle(group.getLabel()); - pref.setUsageSummary(groupUsage, accessTimeStr); - pref.setTitleIcons(Collections.singletonList(group.getIconResId())); - pref.setKey(group.getApp().packageName + "," + group.getName()); - pref.useSmallerIcon(); - pref.setRightIcon(context.getDrawable(R.drawable.ic_settings_outline)); - return pref; - } - - /** - * Compare two usages by whichever app was used most recently. If the two represent the same - * app, sort by which group was used most recently. - * - * Can be used as a {@link java.util.Comparator}. - * - * @param x a usage. - * @param y a usage. - * - * @return see {@link java.util.Comparator#compare(Object, Object)}. - */ - private static int compareAccessAppRecency(@NonNull Pair<AppPermissionUsage, GroupUsage> x, - @NonNull Pair<AppPermissionUsage, GroupUsage> y) { - if (x.first.getApp().getKey().equals(y.first.getApp().getKey())) { - return compareAccessTime(x.second, y.second); - } - return compareAccessTime(x.first, y.first); - } - - /** - * Compare two usages by their access time. - * - * Can be used as a {@link java.util.Comparator}. - * - * @param x a usage. - * @param y a usage. - * - * @return see {@link java.util.Comparator#compare(Object, Object)}. - */ - private static int compareAccessTime(@NonNull Pair<AppPermissionUsage, GroupUsage> x, - @NonNull Pair<AppPermissionUsage, GroupUsage> y) { - return compareAccessTime(x.second, y.second); - } - - /** - * Compare two usages by their access time. - * - * Can be used as a {@link java.util.Comparator}. - * - * @param x a usage. - * @param y a usage. - * - * @return see {@link java.util.Comparator#compare(Object, Object)}. - */ - private static int compareAccessTime(@NonNull GroupUsage x, @NonNull GroupUsage y) { - final int timeDiff = compareLong(x.getLastAccessTime(), y.getLastAccessTime()); - if (timeDiff != 0) { - return timeDiff; - } - // Make sure we lose no data if same - return x.hashCode() - y.hashCode(); - } - - /** - * Compare two AppPermissionUsage by their access time. - * - * Can be used as a {@link java.util.Comparator}. - * - * @param x an AppPermissionUsage. - * @param y an AppPermissionUsage. - * - * @return see {@link java.util.Comparator#compare(Object, Object)}. - */ - private static int compareAccessTime(@NonNull AppPermissionUsage x, - @NonNull AppPermissionUsage y) { - final int timeDiff = compareLong(x.getLastAccessTime(), y.getLastAccessTime()); - if (timeDiff != 0) { - return timeDiff; - } - // Make sure we lose no data if same - return x.hashCode() - y.hashCode(); - } - - /** - * Compare two longs. - * - * Can be used as a {@link java.util.Comparator}. - * - * @param x the first long. - * @param y the second long. - * - * @return see {@link java.util.Comparator#compare(Object, Object)}. - */ - private static int compareLong(long x, long y) { - if (x > y) { - return -1; - } else if (x < y) { - return 1; - } - return 0; - } - - /** - * Compare two usages by recency of access. - * - * Can be used as a {@link java.util.Comparator}. - * - * @param x a usage. - * @param y a usage. - * - * @return see {@link java.util.Comparator#compare(Object, Object)}. - */ - private static int compareAccessRecency(@NonNull Pair<AppPermissionUsage, GroupUsage> x, - @NonNull Pair<AppPermissionUsage, GroupUsage> y) { - final int timeDiff = compareAccessTime(x, y); - if (timeDiff != 0) { - return timeDiff; - } - // Make sure we lose no data if same - return x.hashCode() - y.hashCode(); - } - - /** - * Get the permission groups declared by the OS. - * - * @return a list of the permission groups declared by the OS. - */ - private @NonNull List<AppPermissionGroup> getOSPermissionGroups() { - final List<AppPermissionGroup> groups = new ArrayList<>(); - final Set<String> seenGroups = new ArraySet<>(); - final int numGroups = mAppPermissionUsages.size(); - for (int i = 0; i < numGroups; i++) { - final AppPermissionUsage appUsage = mAppPermissionUsages.get(i); - final List<GroupUsage> groupUsages = appUsage.getGroupUsages(); - final int groupUsageCount = groupUsages.size(); - for (int j = 0; j < groupUsageCount; j++) { - final GroupUsage groupUsage = groupUsages.get(j); - if (Utils.isModernPermissionGroup(groupUsage.getGroup().getName())) { - if (seenGroups.add(groupUsage.getGroup().getName())) { - groups.add(groupUsage.getGroup()); - } - } - } - } - return groups; - } - - /** - * Get an AppPermissionGroup that represents the given permission group (and an arbitrary app). - * - * @param groupName The name of the permission group. - * - * @return an AppPermissionGroup rerepsenting the given permission group or null if no such - * AppPermissionGroup is found. - */ - private @Nullable AppPermissionGroup getGroup(@NonNull String groupName) { - List<AppPermissionGroup> groups = getOSPermissionGroups(); - int numGroups = groups.size(); - for (int i = 0; i < numGroups; i++) { - if (groups.get(i).getName().equals(groupName)) { - return groups.get(i); - } - } - return null; - } - - /** - * Show a dialog that allows selecting a permission group by which to filter the entries. - */ - private void showPermissionFilterDialog() { - Context context = getPreferenceManager().getContext(); - - // Get the permission labels. - List<AppPermissionGroup> groups = getOSPermissionGroups(); - groups.sort( - (x, y) -> mCollator.compare(x.getLabel().toString(), y.getLabel().toString())); - - // Create the dialog entries. - String[] groupNames = new String[groups.size() + 1]; - CharSequence[] groupLabels = new CharSequence[groupNames.length]; - int[] groupAccessCounts = new int[groupNames.length]; - groupNames[0] = null; - groupLabels[0] = context.getString(R.string.permission_usage_any_permission); - Integer allAccesses = mGroupAppCounts.get(null); - if (allAccesses == null) { - allAccesses = 0; - } - groupAccessCounts[0] = allAccesses; - int selection = 0; - int numGroups = groups.size(); - for (int i = 0; i < numGroups; i++) { - AppPermissionGroup group = groups.get(i); - groupNames[i + 1] = group.getName(); - groupLabels[i + 1] = group.getLabel(); - Integer appCount = mGroupAppCounts.get(group.getName()); - if (appCount == null) { - appCount = 0; - } - groupAccessCounts[i + 1] = appCount; - if (group.getName().equals(mFilterGroup)) { - selection = i + 1; - } - } - - // Create the dialog - Bundle args = new Bundle(); - args.putCharSequence(PermissionsFilterDialog.TITLE, - context.getString(R.string.filter_by_title)); - args.putCharSequenceArray(PermissionsFilterDialog.ELEMS, groupLabels); - args.putInt(PermissionsFilterDialog.SELECTION, selection); - args.putStringArray(PermissionsFilterDialog.GROUPS, groupNames); - args.putIntArray(PermissionsFilterDialog.ACCESS_COUNTS, groupAccessCounts); - PermissionsFilterDialog chooserDialog = new PermissionsFilterDialog(); - chooserDialog.setArguments(args); - chooserDialog.setTargetFragment(this, 0); - chooserDialog.show(getFragmentManager().beginTransaction(), - PermissionsFilterDialog.class.getName()); - } - - /** - * Callback when the user selects a permission group by which to filter. - * - * @param selectedGroup The PermissionGroup to use to filter entries, or null if we should show - * all entries. - */ - private void onPermissionGroupSelected(@Nullable String selectedGroup) { - Fragment frag = newInstance(selectedGroup, mFilterTimes.get(mFilterTimeIndex).getTime()); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("PermissionUsage") - .commit(); - } - - /** - * A dialog that allows the user to select a permission group by which to filter entries. - * - * @see #showPermissionFilterDialog() - */ - public static class PermissionsFilterDialog extends DialogFragment { - private static final String TITLE = PermissionsFilterDialog.class.getName() + ".arg.title"; - private static final String ELEMS = PermissionsFilterDialog.class.getName() + ".arg.elems"; - private static final String SELECTION = PermissionsFilterDialog.class.getName() - + ".arg.selection"; - private static final String GROUPS = PermissionsFilterDialog.class.getName() - + ".arg.groups"; - private static final String ACCESS_COUNTS = PermissionsFilterDialog.class.getName() - + ".arg.access_counts"; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder b = new AlertDialog.Builder(getActivity()) - .setView(createDialogView()); - - return b.create(); - } - - private @NonNull View createDialogView() { - PermissionUsageFragment fragment = (PermissionUsageFragment) getTargetFragment(); - CharSequence[] elems = getArguments().getCharSequenceArray(ELEMS); - String[] groups = getArguments().getStringArray(GROUPS); - int[] accessCounts = getArguments().getIntArray(ACCESS_COUNTS); - int selectedIndex = getArguments().getInt(SELECTION); - - LayoutInflater layoutInflater = LayoutInflater.from(fragment.getActivity()); - View view = layoutInflater.inflate(R.layout.permission_filter_dialog, null); - ViewGroup itemsListView = view.requireViewById(R.id.items_container); - - ((TextView) view.requireViewById(R.id.title)).setText( - getArguments().getCharSequence(TITLE)); - - ActionBarShadowController.attachToView(view.requireViewById(R.id.title_container), - getLifecycle(), view.requireViewById(R.id.scroll_view)); - - for (int i = 0; i < elems.length; i++) { - String groupName = groups[i]; - View itemView = layoutInflater.inflate(R.layout.permission_filter_dialog_item, - itemsListView, false); - - ((TextView) itemView.requireViewById(R.id.title)).setText(elems[i]); - ((TextView) itemView.requireViewById(R.id.summary)).setText( - getActivity().getResources().getQuantityString( - R.plurals.permission_usage_permission_filter_subtitle, - accessCounts[i], accessCounts[i])); - - itemView.setOnClickListener((v) -> { - dismissAllowingStateLoss(); - fragment.onPermissionGroupSelected(groupName); - }); - - RadioButton radioButton = itemView.requireViewById(R.id.radio_button); - radioButton.setChecked(i == selectedIndex); - radioButton.setOnClickListener((v) -> { - dismissAllowingStateLoss(); - fragment.onPermissionGroupSelected(groupName); - }); - - itemsListView.addView(itemView); - } - - return view; - } - } - - private void showTimeFilterDialog() { - Context context = getPreferenceManager().getContext(); - - CharSequence[] labels = new CharSequence[mFilterTimes.size()]; - for (int i = 0; i < labels.length; i++) { - labels[i] = mFilterTimes.get(i).getLabel(); - } - - // Create the dialog - Bundle args = new Bundle(); - args.putCharSequence(TimeFilterDialog.TITLE, - context.getString(R.string.filter_by_title)); - args.putCharSequenceArray(TimeFilterDialog.ELEMS, labels); - args.putInt(TimeFilterDialog.SELECTION, mFilterTimeIndex); - TimeFilterDialog chooserDialog = new TimeFilterDialog(); - chooserDialog.setArguments(args); - chooserDialog.setTargetFragment(this, 0); - chooserDialog.show(getFragmentManager().beginTransaction(), - TimeFilterDialog.class.getName()); - } - - /** - * Callback when the user selects a time by which to filter. - * - * @param selectedIndex The index of the dialog option selected by the user. - */ - private void onTimeSelected(int selectedIndex) { - mFilterTimeIndex = selectedIndex; - reloadData(); - } - - /** - * A dialog that allows the user to select a time by which to filter entries. - * - * @see #showTimeFilterDialog() - */ - public static class TimeFilterDialog extends DialogFragment { - private static final String TITLE = TimeFilterDialog.class.getName() + ".arg.title"; - private static final String ELEMS = TimeFilterDialog.class.getName() + ".arg.elems"; - private static final String SELECTION = TimeFilterDialog.class.getName() + ".arg.selection"; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - PermissionUsageFragment fragment = (PermissionUsageFragment) getTargetFragment(); - CharSequence[] elems = getArguments().getCharSequenceArray(ELEMS); - AlertDialog.Builder b = new AlertDialog.Builder(getActivity()) - .setTitle(getArguments().getCharSequence(TITLE)) - .setSingleChoiceItems(elems, getArguments().getInt(SELECTION), - (dialog, which) -> { - dismissAllowingStateLoss(); - fragment.onTimeSelected(which); - } - ); - - return b.create(); - } - } - - /** - * A class representing a given time, e.g., "in the last hour". - */ - private static class TimeFilterItem { - private final long mTime; - private final @NonNull String mLabel; - private final @StringRes int mListTitleRes; - private final @StringRes int mGraphTitleRes; - - TimeFilterItem(long time, @NonNull String label, @StringRes int listTitleRes, - @StringRes int graphTitleRes) { - mTime = time; - mLabel = label; - mListTitleRes = listTitleRes; - mGraphTitleRes = graphTitleRes; - } - - /** - * Get the time represented by this object in milliseconds. - * - * @return the time represented by this object. - */ - public long getTime() { - return mTime; - } - - public @NonNull String getLabel() { - return mLabel; - } - - public @StringRes int getListTitleRes() { - return mListTitleRes; - } - - public @StringRes int getGraphTitleRes() { - return mGraphTitleRes; - } - } -} diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ReviewOngoingUsageFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ReviewOngoingUsageFragment.java deleted file mode 100644 index 623d20f2..00000000 --- a/src/com/android/packageinstaller/permission/ui/handheld/ReviewOngoingUsageFragment.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.packageinstaller.permission.ui.handheld; - -import static android.Manifest.permission_group.CAMERA; -import static android.Manifest.permission_group.LOCATION; -import static android.Manifest.permission_group.MICROPHONE; - -import static com.android.packageinstaller.PermissionControllerStatsLog.PRIVACY_INDICATORS_INTERACTED; -import static com.android.packageinstaller.PermissionControllerStatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_DISMISS; -import static com.android.packageinstaller.PermissionControllerStatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_LINE_ITEM; -import static com.android.packageinstaller.PermissionControllerStatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_PRIVACY_SETTINGS; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.UserHandle; -import android.provider.Settings; -import android.util.ArraySet; -import android.util.Pair; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.preference.PreferenceFragmentCompat; - -import com.android.packageinstaller.PermissionControllerStatsLog; -import com.android.packageinstaller.permission.model.AppPermissionUsage; -import com.android.packageinstaller.permission.model.AppPermissionUsage.GroupUsage; -import com.android.packageinstaller.permission.model.PermissionApps; -import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; -import com.android.packageinstaller.permission.model.PermissionUsages; -import com.android.packageinstaller.permission.utils.Utils; -import com.android.permissioncontroller.R; - -import java.text.Collator; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * A dialog listing the currently uses of camera, microphone, and location. - */ -public class ReviewOngoingUsageFragment extends PreferenceFragmentCompat { - - private @NonNull PermissionUsages mPermissionUsages; - private @Nullable AlertDialog mDialog; - private long mStartTime; - - /** - * @return A new {@link ReviewOngoingUsageFragment} - */ - public static ReviewOngoingUsageFragment newInstance(long numMillis) { - ReviewOngoingUsageFragment fragment = new ReviewOngoingUsageFragment(); - Bundle arguments = new Bundle(); - arguments.putLong(Intent.EXTRA_DURATION_MILLIS, numMillis); - fragment.setArguments(arguments); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (!Utils.isPermissionsHubEnabled()) { - getActivity().finish(); - return; - } - - long numMillis = getArguments().getLong(Intent.EXTRA_DURATION_MILLIS); - - mPermissionUsages = new PermissionUsages(getActivity()); - mStartTime = Math.max(System.currentTimeMillis() - numMillis, Instant.EPOCH.toEpochMilli()); - mPermissionUsages.load(null, new String[]{CAMERA, LOCATION, MICROPHONE}, mStartTime, - Long.MAX_VALUE, PermissionUsages.USAGE_FLAG_LAST, getActivity().getLoaderManager(), - false, false, this::onPermissionUsagesLoaded, false); - } - - private void onPermissionUsagesLoaded() { - if (getActivity() == null) { - return; - } - - List<AppPermissionUsage> appPermissionUsages = mPermissionUsages.getUsages(); - - List<Pair<AppPermissionUsage, List<GroupUsage>>> usages = new ArrayList<>(); - ArrayList<PermissionApp> permApps = new ArrayList<>(); - int numApps = appPermissionUsages.size(); - for (int appNum = 0; appNum < numApps; appNum++) { - AppPermissionUsage appUsage = appPermissionUsages.get(appNum); - - List<GroupUsage> usedGroups = new ArrayList<>(); - List<GroupUsage> appGroups = appUsage.getGroupUsages(); - int numGroups = appGroups.size(); - for (int groupNum = 0; groupNum < numGroups; groupNum++) { - GroupUsage groupUsage = appGroups.get(groupNum); - String groupName = groupUsage.getGroup().getName(); - - if (groupUsage.getLastAccessTime() < mStartTime && !groupUsage.isRunning()) { - continue; - } - if (!Utils.isGroupOrBgGroupUserSensitive(groupUsage.getGroup())) { - continue; - } - - usedGroups.add(appGroups.get(groupNum)); - } - - if (!usedGroups.isEmpty()) { - usages.add(Pair.create(appUsage, usedGroups)); - permApps.add(appUsage.getApp()); - } - } - - if (usages.isEmpty()) { - getActivity().finish(); - return; - } - - new PermissionApps.AppDataLoader(getActivity(), () -> showDialog(usages)) - .execute(permApps.toArray(new PermissionApps.PermissionApp[permApps.size()])); - } - - private void showDialog(@NonNull List<Pair<AppPermissionUsage, List<GroupUsage>>> usages) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) - .setView(createDialogView(usages)) - .setPositiveButton(R.string.ongoing_usage_dialog_ok, (dialog, which) -> - PermissionControllerStatsLog.write(PRIVACY_INDICATORS_INTERACTED, - PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_DISMISS, null)) - .setOnDismissListener((dialog) -> getActivity().finish()); - setNeutralButton(builder); - mDialog = builder.create(); - mDialog.show(); - } - - protected void setNeutralButton(AlertDialog.Builder builder) { - builder.setNeutralButton(R.string.ongoing_usage_dialog_open_settings, (dialog, which) -> { - PermissionControllerStatsLog.write(PRIVACY_INDICATORS_INTERACTED, - PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_PRIVACY_SETTINGS, null); - startActivity(new Intent(Settings.ACTION_PRIVACY_SETTINGS).putExtra( - Intent.EXTRA_DURATION_MILLIS, TimeUnit.MINUTES.toMillis(1))); - }); - } - - private @NonNull View createDialogView( - @NonNull List<Pair<AppPermissionUsage, List<GroupUsage>>> usages) { - Context context = getActivity(); - LayoutInflater inflater = LayoutInflater.from(context); - View contentView = inflater.inflate(R.layout.ongoing_usage_dialog_content, null); - ViewGroup appsList = contentView.requireViewById(R.id.items_container); - - // Compute all of the permission group labels that were used. - ArraySet<String> usedGroups = new ArraySet<>(); - int numUsages = usages.size(); - for (int usageNum = 0; usageNum < numUsages; usageNum++) { - List<GroupUsage> groups = usages.get(usageNum).second; - int numGroups = groups.size(); - for (int groupNum = 0; groupNum < numGroups; groupNum++) { - usedGroups.add(groups.get(groupNum).getGroup().getLabel().toString().toLowerCase()); - } - } - - // Add the layout for each app. - for (int usageNum = 0; usageNum < numUsages; usageNum++) { - Pair<AppPermissionUsage, List<GroupUsage>> usage = usages.get(usageNum); - PermissionApp app = usage.first.getApp(); - List<GroupUsage> groups = usage.second; - - View itemView = inflater.inflate(R.layout.ongoing_usage_dialog_item, appsList, false); - - ((TextView) itemView.requireViewById(R.id.app_name)).setText(app.getLabel()); - ((ImageView) itemView.requireViewById(R.id.app_icon)).setImageDrawable(app.getIcon()); - - // Add the icons for the groups this app used as long as multiple groups were used by - // some app. - if (usedGroups.size() > 1) { - ViewGroup iconFrame = itemView.requireViewById(R.id.icons); - int numGroups = usages.get(usageNum).second.size(); - for (int groupNum = 0; groupNum < numGroups; groupNum++) { - ViewGroup group = (ViewGroup) inflater.inflate(R.layout.image_view, null); - ((ImageView) group.requireViewById(R.id.icon)).setImageDrawable( - Utils.applyTint(context, groups.get(groupNum).getGroup().getIconResId(), - android.R.attr.colorControlNormal)); - iconFrame.addView(group); - } - iconFrame.setVisibility(View.VISIBLE); - } - - itemView.setOnClickListener((v) -> { - String packageName = app.getPackageName(); - PermissionControllerStatsLog.write(PRIVACY_INDICATORS_INTERACTED, - PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_LINE_ITEM, packageName); - UserHandle user = UserHandle.getUserHandleForUid(app.getUid()); - Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(Intent.EXTRA_USER, user); - context.startActivity(intent); - mDialog.dismiss(); - }); - - appsList.addView(itemView); - } - - // Set the title of the dialog based on all of the permissions used. - StringBuilder titleBuilder = new StringBuilder(); - int numGroups = usedGroups.size(); - List<String> sortedGroups = new ArrayList<>(usedGroups); - Collator collator = Collator.getInstance( - getResources().getConfiguration().getLocales().get(0)); - sortedGroups.sort(collator); - for (int i = 0; i < numGroups; i++) { - titleBuilder.append(sortedGroups.get(i)); - if (i < numGroups - 2) { - titleBuilder.append(getString(R.string.ongoing_usage_dialog_separator)); - } else if (i < numGroups - 1) { - titleBuilder.append(getString(R.string.ongoing_usage_dialog_last_separator)); - } - } - - ((TextView) contentView.requireViewById(R.id.title)).setText( - getString(R.string.ongoing_usage_dialog_title, titleBuilder.toString())); - - return contentView; - } - - @Override - public void onCreatePreferences(Bundle bundle, String s) { - // empty - } -} diff --git a/src/com/android/packageinstaller/permission/utils/Utils.java b/src/com/android/packageinstaller/permission/utils/Utils.java index 867d603c..707b9f7b 100644 --- a/src/com/android/packageinstaller/permission/utils/Utils.java +++ b/src/com/android/packageinstaller/permission/utils/Utils.java @@ -84,7 +84,6 @@ import com.android.launcher3.icons.IconFactory; import com.android.packageinstaller.Constants; import com.android.packageinstaller.permission.data.PerUserUidToSensitivityLiveData; import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissionUsage; import com.android.permissioncontroller.R; import java.util.ArrayList; @@ -102,9 +101,6 @@ public final class Utils { public static final float DEFAULT_MAX_LABEL_SIZE_PX = 500f; - /** Whether to show the Permissions Hub. */ - private static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled"; - /** Whether to show location access check notifications. */ private static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "location_access_check_enabled"; @@ -570,39 +566,6 @@ public final class Utils { } /** - * Build a string representing the amount of time passed since the most recent permission usage. - * - * @return a string representing the amount of time since this app's most recent permission - * usage or null if there are no usages. - */ - public static @Nullable String getRelativeLastUsageString(@NonNull Context context, - @Nullable AppPermissionUsage.GroupUsage groupUsage) { - if (groupUsage == null || groupUsage.getLastAccessTime() == 0) { - return null; - } - return getTimeDiffStr(context, System.currentTimeMillis() - - groupUsage.getLastAccessTime()); - } - - /** - * Build a string representing the time of the most recent permission usage if it happened on - * the current day and the date otherwise. - * - * @param context the context. - * @param groupUsage the permission usage. - * - * @return a string representing the time or date of the most recent usage or null if there are - * no usages. - */ - public static @Nullable String getAbsoluteLastUsageString(@NonNull Context context, - @Nullable AppPermissionUsage.GroupUsage groupUsage) { - if (groupUsage == null) { - return null; - } - return getAbsoluteTimeString(context, groupUsage.getLastAccessTime()); - } - - /** * Build a string representing the given time if it happened on the current day and the date * otherwise. * @@ -624,20 +587,6 @@ public final class Utils { } /** - * Build a string representing the duration of a permission usage. - * - * @return a string representing the duration of this app's usage or null if there are no - * usages. - */ - public static @Nullable String getUsageDurationString(@NonNull Context context, - @Nullable AppPermissionUsage.GroupUsage groupUsage) { - if (groupUsage == null) { - return null; - } - return getTimeDiffStr(context, groupUsage.getAccessDuration()); - } - - /** * Build a string representing the number of milliseconds passed in. It rounds to the nearest * unit. For example, given a duration of 3500 and an English locale, this can return * "3 seconds". @@ -778,27 +727,6 @@ public final class Utils { } /** - * Whether the Permissions Hub is enabled. - * - * @return whether the Permissions Hub is enabled. - */ - public static boolean isPermissionsHubEnabled() { - return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - PROPERTY_PERMISSIONS_HUB_ENABLED, false); - } - - /** - * Whether we should show permission usages for the specified permission group. - * - * @param permissionGroup The name of the permission group. - * - * @return whether or not to show permission usages for the given permission group. - */ - public static boolean shouldShowPermissionUsage(@NonNull String permissionGroup) { - return !permissionGroup.equals(STORAGE); - } - - /** * Get a device protected storage based shared preferences. Avoid storing sensitive data in it. * * @param context the context to get the shared preferences |