From b04fa22a5525782ec4ff48488d18e73534caedff Mon Sep 17 00:00:00 2001 From: Muntashir Al-Islam Date: Tue, 19 Nov 2024 10:44:52 -0800 Subject: [PATCH] [Finder] Add new filter: permissions Signed-off-by: Muntashir Al-Islam --- .../AppManager/filters/FilterableAppInfo.java | 7 +- .../filters/options/FilterOption.java | 10 ++ .../filters/options/FilterOptions.java | 2 +- .../filters/options/PermissionsOption.java | 101 ++++++++++++++++++ 4 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/io/github/muntashirakon/AppManager/filters/options/PermissionsOption.java diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/FilterableAppInfo.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/FilterableAppInfo.java index 20dd6a0f8bd..daaeb062506 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/filters/FilterableAppInfo.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/FilterableAppInfo.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; @@ -72,7 +73,7 @@ public class FilterableAppInfo { private String[] mSignatureSha256Checksums; private Map mAllComponents; private Map mTrackerComponents; - private String[] mUsedPermissions; + private List mUsedPermissions; private Backup[] mBackups; private List mAppOpEntries; @Nullable @@ -211,7 +212,7 @@ public Map getAllComponents() { } @NonNull - public String[] getAllPermissions() { + public List getAllPermissions() { if (mUsedPermissions == null) { Set usedPermissions = new HashSet<>(); if (mPackageInfo.requestedPermissions != null) { @@ -243,7 +244,7 @@ public String[] getAllPermissions() { } } } - mUsedPermissions = usedPermissions.toArray(new String[0]); + mUsedPermissions = new ArrayList<>(usedPermissions); } return mUsedPermissions; } diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOption.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOption.java index 3d9375e5408..0a9d1f764b7 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOption.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOption.java @@ -168,6 +168,7 @@ public static class TestResult { private List mMatchedBackups; private Map mMatchedComponents; private Map mMatchedTrackers; + private List mMatchedPermissions; private List mMatchedSubjectLines; public TestResult setMatched(boolean matched) { @@ -209,6 +210,15 @@ public Map getMatchedTrackers() { return mMatchedTrackers; } + public TestResult setMatchedPermissions(List matchedPermissions) { + mMatchedPermissions = matchedPermissions; + return this; + } + + public List getMatchedPermissions() { + return mMatchedPermissions; + } + public TestResult setMatchedSubjectLines(List matchedSubjectLines) { mMatchedSubjectLines = matchedSubjectLines; return this; diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOptions.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOptions.java index b954e4449bc..72eccfb0aae 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOptions.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/FilterOptions.java @@ -20,7 +20,7 @@ public static FilterOption create(@NonNull String filterName) { case "installer": return new InstallerOption(); case "last_update": return new LastUpdateOption(); case "min_sdk": return new MinSdkOption(); - // case "permission": return new PermissionOption(); + case "permissions": return new PermissionsOption(); case "pkg_name": return new PackageNameOption(); case "running_apps": return new RunningAppsOption(); case "screen_time": return new ScreenTimeOption(); diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/PermissionsOption.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/PermissionsOption.java new file mode 100644 index 00000000000..830077a65c0 --- /dev/null +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/PermissionsOption.java @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package io.github.muntashirakon.AppManager.filters.options; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import io.github.muntashirakon.AppManager.filters.FilterableAppInfo; + +public class PermissionsOption extends FilterOption { + private final Map mKeysWithType = new LinkedHashMap() {{ + put(KEY_ALL, TYPE_NONE); + put("eq", TYPE_STR_SINGLE); + put("contains", TYPE_STR_SINGLE); + put("starts_with", TYPE_STR_SINGLE); + put("ends_with", TYPE_STR_SINGLE); + put("regex", TYPE_REGEX); + // TODO: 11/19/24 Add more curated options such as permission flags, private flags, grant + }}; + + public PermissionsOption() { + super("permissions"); + } + + @NonNull + @Override + public Map getKeysWithType() { + return mKeysWithType; + } + + @NonNull + @Override + public TestResult test(@NonNull FilterableAppInfo info, @NonNull TestResult result) { + List permissions = result.getMatchedPermissions() != null + ? result.getMatchedPermissions() + : info.getAllPermissions(); + switch (key) { + default: + return result.setMatched(true).setMatchedPermissions(permissions); + case "eq": { + List filteredPermissions = new ArrayList<>(); + for (String permission : permissions) { + if (permission.equals(value)) { + filteredPermissions.add(permission); + } + } + return result.setMatched(!filteredPermissions.isEmpty()) + .setMatchedPermissions(filteredPermissions); + } + case "contains": { + Objects.requireNonNull(value); + List filteredPermissions = new ArrayList<>(); + for (String permission : permissions) { + if (permission.contains(value)) { + filteredPermissions.add(permission); + } + } + return result.setMatched(!filteredPermissions.isEmpty()) + .setMatchedPermissions(filteredPermissions); + } + case "starts_with": { + Objects.requireNonNull(value); + List filteredPermissions = new ArrayList<>(); + for (String permission : permissions) { + if (permission.startsWith(value)) { + filteredPermissions.add(permission); + } + } + return result.setMatched(!filteredPermissions.isEmpty()) + .setMatchedPermissions(filteredPermissions); + } + case "ends_with": { + Objects.requireNonNull(value); + List filteredPermissions = new ArrayList<>(); + for (String permission : permissions) { + if (permission.endsWith(value)) { + filteredPermissions.add(permission); + } + } + return result.setMatched(!filteredPermissions.isEmpty()) + .setMatchedPermissions(filteredPermissions); + } + case "regex": { + Objects.requireNonNull(value); + List filteredPermissions = new ArrayList<>(); + for (String permission : permissions) { + if (regexValue.matcher(permission).matches()) { + filteredPermissions.add(permission); + } + } + return result.setMatched(!filteredPermissions.isEmpty()) + .setMatchedPermissions(filteredPermissions); + } + } + } +}