Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3c00c29 authored by Patrick Baumann's avatar Patrick Baumann
Browse files

Cache app enumeration per-package enabled state

This change queries PlatformCompat for state on package add and when the
state is changed (notified via listener) to avoid expensive
transformation to ApplicationInfo and any performance impact
PlatformCompat may itself have.

Bug: 149768323
Test: atest PackageManagerPerfTests AppEnumerationTests
Change-Id: I19d8d0918ca6d0563e86a0c84e07cb2c0202543f
parent da458559
Loading
Loading
Loading
Loading
+55 −7
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.annotation.Nullable;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.parsing.AndroidPackage;
import android.content.pm.parsing.ComponentParseUtils;
@@ -49,6 +50,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.FgThread;
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;

import java.io.PrintWriter;
@@ -129,15 +131,25 @@ public class AppsFilter {

        /** @return true if the feature is enabled for the given package. */
        boolean packageIsEnabled(AndroidPackage pkg);

        /**
         * Initializes the package enablement state for the given package. This gives opportunity
         * to do any expensive operations ahead of the actual checks.
         */
        void initializePackageState(String packageName);
    }

    private static class FeatureConfigImpl implements FeatureConfig {
    private static class FeatureConfigImpl implements FeatureConfig, CompatChange.ChangeListener {
        private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled";
        private final PackageManagerService.Injector mInjector;
        private final PackageManagerInternal mPmInternal;
        private volatile boolean mFeatureEnabled =
                PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT;
        private final ArraySet<String> mDisabledPackages = new ArraySet<>();

        private FeatureConfigImpl(PackageManagerService.Injector injector) {
        private FeatureConfigImpl(
                PackageManagerInternal pmInternal, PackageManagerService.Injector injector) {
            mPmInternal = pmInternal;
            mInjector = injector;
        }

@@ -156,6 +168,8 @@ public class AppsFilter {
                            }
                        }
                    });
            mInjector.getCompatibility().registerListener(
                    PackageManager.FILTER_APPLICATION_QUERY, this);
        }

        @Override
@@ -171,23 +185,55 @@ public class AppsFilter {
        @Override
        public boolean packageIsEnabled(AndroidPackage pkg) {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "packageIsEnabled");
            try {
                return !mDisabledPackages.contains(pkg.getPackageName());
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

        private boolean fetchPackageIsEnabled(AndroidPackage pkg) {
            final long token = Binder.clearCallingIdentity();
            try {
                // TODO(b/135203078): Do not use toAppInfo
                return mInjector.getCompatibility().isChangeEnabled(
                        PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
                final boolean changeEnabled =
                        mInjector.getCompatibility().isChangeEnabled(
                                PackageManager.FILTER_APPLICATION_QUERY,
                                pkg.toAppInfoWithoutState());
                return changeEnabled;
            } finally {
                Binder.restoreCallingIdentity(token);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

        @Override
        public void onCompatChange(String packageName) {
            final AndroidPackage pkg = mPmInternal.getPackage(packageName);
            if (pkg == null) {
                mDisabledPackages.remove(packageName);
                return;
            }
            boolean enabled = fetchPackageIsEnabled(pkg);
            if (enabled) {
                mDisabledPackages.remove(packageName);
            } else {
                mDisabledPackages.add(packageName);
            }
        }

        @Override
        public void initializePackageState(String packageName) {
            onCompatChange(packageName);
        }
    }

    public static AppsFilter create(PackageManagerService.Injector injector) {
    /** Builder method for an AppsFilter */
    public static AppsFilter create(
            PackageManagerInternal pms, PackageManagerService.Injector injector) {
        final boolean forceSystemAppsQueryable =
                injector.getContext().getResources()
                        .getBoolean(R.bool.config_forceSystemPackagesQueryable);
        final FeatureConfig featureConfig = new FeatureConfigImpl(injector);
        final FeatureConfig featureConfig = new FeatureConfigImpl(pms, injector);
        final String[] forcedQueryablePackageNames;
        if (forceSystemAppsQueryable) {
            // all system apps already queryable, no need to read and parse individual exceptions
@@ -400,6 +446,7 @@ public class AppsFilter {
                }
            }
            mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs);
            mFeatureConfig.initializePackageState(newPkgSetting.pkg.getPackageName());
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
@@ -451,6 +498,7 @@ public class AppsFilter {
        }

        mOverlayReferenceMapper.removePkg(setting.name);
        mFeatureConfig.initializePackageState(setting.pkg.getPackageName());
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -2489,7 +2489,7 @@ public class PackageManagerService extends IPackageManager.Stub
                new Injector.SystemServiceProducer<>(DisplayManager.class),
                new Injector.SystemServiceProducer<>(StorageManager.class),
                new Injector.SystemServiceProducer<>(AppOpsManager.class),
                (i, pm) -> AppsFilter.create(i),
                (i, pm) -> AppsFilter.create(pm.mPmInternal, i),
                (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"));
        PackageManagerService m = new PackageManagerService(injector, factoryTest, onlyCore);