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 00470910aa9..20dd6a0f8bd 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 @@ -48,7 +48,6 @@ import io.github.muntashirakon.AppManager.types.PackageSizeInfo; import io.github.muntashirakon.AppManager.usage.AppUsageStatsManager; import io.github.muntashirakon.AppManager.usage.PackageUsageInfo; -import io.github.muntashirakon.AppManager.usage.UsageUtils; import io.github.muntashirakon.AppManager.utils.ArrayUtils; import io.github.muntashirakon.AppManager.utils.ContextUtils; import io.github.muntashirakon.AppManager.utils.DigestUtils; @@ -57,6 +56,8 @@ public class FilterableAppInfo { private final PackageInfo mPackageInfo; + @Nullable + private final PackageUsageInfo mPackageUsageInfo; private final ApplicationInfo mApplicationInfo; private final int mUserId; private final PackageManager mPm; @@ -76,12 +77,12 @@ public class FilterableAppInfo { private List mAppOpEntries; @Nullable private PackageSizeInfo mPackageSizeInfo; - private PackageUsageInfo mPackageUsageInfo; private AppUsageStatsManager.DataUsage mDataUsage; private DebloatObject mBloatwareInfo; - public FilterableAppInfo(@NonNull PackageInfo packageInfo) { + public FilterableAppInfo(@NonNull PackageInfo packageInfo, @Nullable PackageUsageInfo packageUsageInfo) { mPackageInfo = packageInfo; + mPackageUsageInfo = packageUsageInfo; mApplicationInfo = packageInfo.applicationInfo; mUserId = UserHandleHidden.getUserId(mApplicationInfo.uid); mPm = ContextUtils.getContext().getPackageManager(); @@ -383,28 +384,26 @@ public long getDataSize() { public AppUsageStatsManager.DataUsage getDataUsage() { if (mDataUsage == null && isInstalled()) { - mDataUsage = AppUsageStatsManager.getDataUsageForPackage(ContextUtils.getContext(), mApplicationInfo.uid, UsageUtils.USAGE_WEEKLY); - } else mDataUsage = new AppUsageStatsManager.DataUsage(0, 0); - return mDataUsage; - } - - private void fetchPackageUsageInfo() { - if (mPackageUsageInfo == null && isInstalled()) { - try { - mPackageUsageInfo = AppUsageStatsManager.getInstance().getUsageStatsForPackage(getPackageName(), UsageUtils.USAGE_WEEKLY, mUserId); - } catch (Exception ignore) { + if (mPackageUsageInfo != null) { + mDataUsage = AppUsageStatsManager.DataUsage.fromDataUsage(mPackageUsageInfo.mobileData, mPackageUsageInfo.wifiData); } } + if (mDataUsage == null) { + mDataUsage = AppUsageStatsManager.DataUsage.EMPTY; + } + return mDataUsage; } public int getTimesOpened() { - fetchPackageUsageInfo(); return mPackageUsageInfo != null ? mPackageUsageInfo.timesOpened : 0; } public long getTotalScreenTime() { - fetchPackageUsageInfo(); - return mPackageUsageInfo != null ? mPackageUsageInfo.screenTime : 0; + return mPackageUsageInfo != null ? mPackageUsageInfo.screenTime : 0L; + } + + public long getLastUsedTime() { + return mPackageUsageInfo != null ? mPackageUsageInfo.lastUsageTime : 0L; } @Nullable diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/FinderViewModel.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/FinderViewModel.java index f6cd9dba25c..6bf46dcc332 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/filters/FinderViewModel.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/FinderViewModel.java @@ -20,10 +20,18 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Future; import io.github.muntashirakon.AppManager.compat.PackageManagerCompat; +import io.github.muntashirakon.AppManager.self.SelfPermissions; +import io.github.muntashirakon.AppManager.settings.FeatureController; +import io.github.muntashirakon.AppManager.usage.AppUsageStatsManager; +import io.github.muntashirakon.AppManager.usage.PackageUsageInfo; +import io.github.muntashirakon.AppManager.usage.UsageUtils; +import io.github.muntashirakon.AppManager.utils.ExUtils; import io.github.muntashirakon.AppManager.utils.ThreadUtils; public class FinderViewModel extends AndroidViewModel { @@ -79,18 +87,32 @@ private void loadAppList() { // TODO: 8/2/24 Include backups for uninstalled apps int[] userIds = new int[]{UserHandleHidden.myUserId()}; //Users.getUsersIds(); List filterableAppInfoList = new ArrayList<>(); + boolean hasUsageAccess = FeatureController.isUsageAccessEnabled() && SelfPermissions.checkUsageStatsPermission(); for (int userId : userIds) { if (ThreadUtils.isInterrupted()) return; + // List packages List packageInfoList = PackageManagerCompat.getInstalledPackages( PackageManager.GET_META_DATA | GET_SIGNING_CERTIFICATES | PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS | PackageManager.GET_SERVICES | MATCH_DISABLED_COMPONENTS | MATCH_UNINSTALLED_PACKAGES | MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, userId); + // List usages + Map packageUsageInfoList = new HashMap<>(); + if (hasUsageAccess) { + List usageInfoList = ExUtils.exceptionAsNull(() -> AppUsageStatsManager.getInstance() + .getUsageStats(UsageUtils.USAGE_WEEKLY, userId)); + if (usageInfoList != null) { + for (PackageUsageInfo info : usageInfoList) { + if (ThreadUtils.isInterrupted()) return; + packageUsageInfoList.put(info.packageName, info); + } + } + } for (PackageInfo packageInfo : packageInfoList) { // Interrupt thread on request if (ThreadUtils.isInterrupted()) return; - filterableAppInfoList.add(new FilterableAppInfo(packageInfo)); + filterableAppInfoList.add(new FilterableAppInfo(packageInfo, packageUsageInfoList.get(packageInfo.packageName))); } } mFilterableAppInfoList = filterableAppInfoList; diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/DataUsageOption.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/DataUsageOption.java index 76df399dafe..42c4fac894b 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/DataUsageOption.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/DataUsageOption.java @@ -15,6 +15,7 @@ public class DataUsageOption extends FilterOption { put("eq", TYPE_SIZE_BYTES); put("le", TYPE_SIZE_BYTES); put("ge", TYPE_SIZE_BYTES); + // TODO: 11/19/24 Add more curated options, e.g., mobile and wifi }}; public DataUsageOption() { diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/InstalledOption.java b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/InstalledOption.java index 51e951dd2ae..0ddfc3a6581 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/InstalledOption.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/InstalledOption.java @@ -13,6 +13,7 @@ public class InstalledOption extends FilterOption { private final Map mKeysWithType = new LinkedHashMap() {{ put("all", TYPE_NONE); put("installed", TYPE_NONE); + put("uninstalled", TYPE_NONE); put("installed_before", TYPE_TIME_MILLIS); put("installed_after", TYPE_TIME_MILLIS); }}; diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/usage/AppUsageStatsManager.java b/app/src/main/java/io/github/muntashirakon/AppManager/usage/AppUsageStatsManager.java index 1f8437398b6..0f60bdb96c0 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/usage/AppUsageStatsManager.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/usage/AppUsageStatsManager.java @@ -67,6 +67,18 @@ public class AppUsageStatsManager { public static final class DataUsage extends Pair implements Parcelable, Comparable { public static final DataUsage EMPTY = new DataUsage(0, 0); + public static DataUsage fromDataUsage(DataUsage ...dataUsages) { + if (dataUsages == null) { + return EMPTY; + } + long tx = 0, rx = 0; + for (DataUsage dataUsage : dataUsages) { + tx += dataUsage.getTx(); + rx += dataUsage.getRx(); + } + return new DataUsage(tx, rx); + } + private final long mTotal; public DataUsage(long tx, long rx) {