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

Commit 72635f67 authored by Lee Shombert's avatar Lee Shombert
Browse files

Binder cache for hasSystemFeature().

System features are build-time constants, so the cache is invalidated only
when the system server restarts.

Bug: 140788621

Test: A special build that puts the PropertyInvalidatedCache in
verification mode was loaded on the device.  Then one iteration of MPTS was
executed.  No cache inconsistencies were found and no SELinux violations
(associated with the binder cache) were found.  The number of cache misses
was approximately 15% of the total binder calls.  98.5% of all binder calls
went through the cache.

Change-Id: Icd23283512ab648ed589d461d2a86e1c3807b45a
parent 310f576b
Loading
Loading
Loading
Loading
+59 −2
Original line number Original line Diff line number Diff line
@@ -618,8 +618,7 @@ public class ApplicationPackageManager extends PackageManager {
        return hasSystemFeature(name, 0);
        return hasSystemFeature(name, 0);
    }
    }


    @Override
    private boolean hasSystemFeatureUncached(String name, int version) {
    public boolean hasSystemFeature(String name, int version) {
        try {
        try {
            return mPM.hasSystemFeature(name, version);
            return mPM.hasSystemFeature(name, version);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
@@ -627,6 +626,64 @@ public class ApplicationPackageManager extends PackageManager {
        }
        }
    }
    }


    // Make this cache relatively large.  There are many system features and
    // none are ever invalidated.  MPTS tests suggests that the cache should
    // hold at least 150 entries.
    private static final int SYS_FEATURE_CACHE_SIZE = 256;
    private static final String CACHE_KEY_SYS_FEATURE_PROPERTY = "cache_key.has_system_feature";

    private class SystemFeatureQuery {
        public final String name;
        public final int version;
        public SystemFeatureQuery(String n, int v) {
            name = n;
            version = v;
        }
        @Override
        public String toString() {
            return String.format("SystemFeatureQuery(name=\"%s\", version=%d)",
                    name, version);
        }
        @Override
        public boolean equals(Object o) {
            if (o instanceof SystemFeatureQuery) {
                SystemFeatureQuery r = (SystemFeatureQuery) o;
                return Objects.equals(name, r.name) &&  version == r.version;
            } else {
                return false;
            }
        }
        @Override
        public int hashCode() {
            return Objects.hashCode(name) + version;
        }
    }

    private final PropertyInvalidatedCache<SystemFeatureQuery, Boolean> mSysFeatureCache =
            new PropertyInvalidatedCache<SystemFeatureQuery, Boolean>(
                SYS_FEATURE_CACHE_SIZE,
                CACHE_KEY_SYS_FEATURE_PROPERTY) {
                @Override
                protected Boolean recompute(SystemFeatureQuery query) {
                    return hasSystemFeatureUncached(query.name, query.version);
                }
            };

    @Override
    public boolean hasSystemFeature(String name, int version) {
        return mSysFeatureCache.query(new SystemFeatureQuery(name, version)).booleanValue();
    }

    /** @hide */
    public void disableSysFeatureCache() {
        mSysFeatureCache.disableLocal();
    }

    /** @hide */
    public static void invalidateSysFeatureCache() {
        PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SYS_FEATURE_PROPERTY);
    }

    @Override
    @Override
    public int checkPermission(String permName, String pkgName) {
    public int checkPermission(String permName, String pkgName) {
        try {
        try {
+2 −0
Original line number Original line Diff line number Diff line
@@ -124,6 +124,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ApplicationPackageManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.IActivityManager;
@@ -2721,6 +2722,7 @@ public class PackageManagerService extends IPackageManager.Stub
        t.traceBegin("get system config");
        t.traceBegin("get system config");
        SystemConfig systemConfig = SystemConfig.getInstance();
        SystemConfig systemConfig = SystemConfig.getInstance();
        mAvailableFeatures = systemConfig.getAvailableFeatures();
        mAvailableFeatures = systemConfig.getAvailableFeatures();
        ApplicationPackageManager.invalidateSysFeatureCache();
        t.traceEnd();
        t.traceEnd();
        mProtectedPackages = new ProtectedPackages(mContext);
        mProtectedPackages = new ProtectedPackages(mContext);