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

Commit 77d90690 authored by Lee Shombert's avatar Lee Shombert
Browse files

Cleanup PIC flags

This removes non-exported PIC flags that have been deployed in 25Q2 or
earlier, and removes any code that is guarded by the flags.

This removes pic_isolated_cache_statistics, which was never deployed.

The public PIC method separatePermissionNotificationsEnabled() is
retained because several external classes reference it.

Flag: EXEMPT removing android.app.pic_uses_shared_memory
Flag: EXEMPT removing android.app.pic_cache_nulls
Flag: EXEMPT removing android.app.pic_isolate_cache_by_uid
Flag: EXEMPT removing android.app.pic_separate_permission_notifications
Flag: EXEMPT removing android.app.pic_isolated_cache_statistics
Bug: 423886240
Bug: 423987010
Bug: 423972381
Test: atest
 * CtsAppEnumerationTestCases
 * CtsMediaAudioPermissionTestCases
 * CtsMediaAudioTestCases:AudioRecordTest
 * CtsOsTestCases:IpcDataCacheTest
 * FrameworksCoreTests:IpcDataCacheTest
 * FrameworksCoreTests:PropertyInvalidatedCacheTests
 * ServiceBluetoothTests
 * android.app.appops.cts.AppOpsLoggingTest
 * android.content.pm.cts.PackageManagerTest
 * android.media.audio.cts.AudioFocusTest
 * com.android.server.pm.PackageManagerTests

Change-Id: Ifa4b0381b1818cb2f3e010df8f80d699bd576bcb
parent 9b769d46
Loading
Loading
Loading
Loading
+4 −217
Original line number Diff line number Diff line
@@ -23,24 +23,17 @@ import static com.android.internal.util.Preconditions.checkArgumentPositive;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SystemPropertySetter;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.ApplicationSharedMemory;
import com.android.internal.os.BackgroundThread;

import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -80,13 +73,11 @@ import java.util.concurrent.atomic.AtomicLong;
public class PropertyInvalidatedCache<Query, Result> {
    /**
     * A method to report if the PermissionManager notifications can be separated from cache
     * invalidation.  The feature relies on a series of flags; the dependency is captured in this
     * method.
     * invalidation.  The feature relies on a series of flags, all of which are committed.
     * @hide
     */
    public static boolean separatePermissionNotificationsEnabled() {
        return isSharedMemoryAvailable()
                && Flags.picSeparatePermissionNotifications();
        return true;
    }

    /**
@@ -496,25 +487,6 @@ public class PropertyInvalidatedCache<Query, Result> {
        // entries to be combined in a single hash map.
        private final boolean mIsolated;

        // Collect statistics.
        private final boolean mStatistics;

        // An array of booleans to indicate if a UID has been involved in a map access.  A value
        // exists for every UID that was ever involved during cache access. This is updated only
        // if statistics are being collected.
        private final SparseBooleanArray mUidSeen;

        // A hash map that ignores the UID.  This is used in look-aside fashion just for hit/miss
        // statistics.  This is updated only if statistics are being collected.
        private final ArraySet<Query> mShadowCache;

        // Shadow statistics.  Only hits and misses need to be recorded.  These are updated only
        // if statistics are being collected.  The "SelfHits" records hits when the UID is the
        // process uid.
        private int mShadowHits;
        private int mShadowMisses;
        private int mShadowSelfHits;

        // The process UID.
        private final int mSelfUid;

@@ -526,15 +498,7 @@ public class PropertyInvalidatedCache<Query, Result> {
         * isolation feature is enabled.
         */
        CacheMap(boolean isolate, boolean testMode) {
            mIsolated = Flags.picIsolateCacheByUid() && isolate;
            mStatistics = Flags.picIsolatedCacheStatistics() && mIsolated;
            if (mStatistics) {
                mUidSeen = new SparseBooleanArray();
                mShadowCache = new ArraySet<>();
            } else {
                mUidSeen = null;
                mShadowCache = null;
            }
            mIsolated = isolate;
            mSelfUid = Process.myUid();
            mTestMode = testMode;
        }
@@ -556,19 +520,6 @@ public class PropertyInvalidatedCache<Query, Result> {
         */
        Result get(Query query) {
            final int uid = callerUid();

            // Shadow statistics
            if (mStatistics) {
                if (mShadowCache.contains(query)) {
                    mShadowHits++;
                    if (uid == mSelfUid) {
                        mShadowSelfHits++;
                    }
                } else {
                    mShadowMisses++;
                }
            }

            var map = mCache.get(uid);
            if (map != null) {
                return map.get(query);
@@ -595,10 +546,6 @@ public class PropertyInvalidatedCache<Query, Result> {
         */
        void remove(Query query) {
            final int uid = callerUid();
            if (mStatistics) {
                mShadowCache.remove(query);
            }

            var map = mCache.get(uid);
            if (map != null) {
                map.remove(query);
@@ -610,11 +557,6 @@ public class PropertyInvalidatedCache<Query, Result> {
         */
        void put(Query query, Result result) {
            final int uid = callerUid();
            if (mStatistics) {
                mShadowCache.add(query);
                mUidSeen.put(uid, true);
            }

            var map = mCache.get(uid);
            if (map == null) {
                map = createMap();
@@ -639,23 +581,9 @@ public class PropertyInvalidatedCache<Query, Result> {
         * Clear the entries in the cache.  Update the shadow statistics.
         */
        void clear() {
            if (mStatistics) {
                mShadowCache.clear();
            }

            mCache.clear();
        }

        // Dump basic statistics, if any are collected.  Do nothing if statistics are not enabled.
        void dump(PrintWriter pw) {
            if (mStatistics) {
                pw.println(formatSimple("    ShadowHits: %d, ShadowMisses: %d, ShadowSize: %d",
                                mShadowHits, mShadowMisses, mShadowCache.size()));
                pw.println(formatSimple("    ShadowUids: %d, SelfUid: %d",
                                mUidSeen.size(), mShadowSelfHits));
            }
        }

        // Dump detailed statistics
        void dumpDetailed(PrintWriter pw) {
            for (int i = 0; i < mCache.size(); i++) {
@@ -1304,19 +1232,10 @@ public class PropertyInvalidatedCache<Query, Result> {
        return false; // Always disable shared memory on Ravenwood. (for now)
    }

    /**
     * Keys that cannot be put in shared memory yet.
     */
    private static boolean inSharedMemoryDenyList(@NonNull String name) {
        final String pkginfo = PREFIX_SYSTEM + "package_info";
        return name.equals(pkginfo);
    }

    // Return true if this cache can use shared memory for its nonce.  Shared memory may be used
    // if the module is the system.
    private static boolean sharedMemoryOkay(@NonNull CacheKey id) {
        return sSharedMemoryAvailable && sNamespaceSystem.equals(id.namespace)
                && !inSharedMemoryDenyList(id.key);
        return sSharedMemoryAvailable && sNamespaceSystem.equals(id.namespace);
    }

    /**
@@ -1936,137 +1855,6 @@ public class PropertyInvalidatedCache<Query, Result> {
        getNonceHandler(name).uncork();
    }

    /**
     * Time-based automatic corking helper. This class allows providers of cached data to
     * amortize the cost of cache invalidations by corking the cache immediately after a
     * modification (instructing clients to bypass the cache temporarily) and automatically
     * uncork after some period of time has elapsed.
     *
     * It's better to use explicit cork and uncork pairs that tighly surround big batches of
     * invalidations, but it's not always practical to tell where these invalidation batches
     * might occur. AutoCorker's time-based corking is a decent alternative.
     *
     * The auto-cork delay is configurable but it should not be too long.  The purpose of
     * the delay is to minimize the number of times a server writes to the system property
     * when invalidating the cache.  One write every 50ms does not hurt system performance.
     * @hide
     */
    public static final class AutoCorker {
        public static final int DEFAULT_AUTO_CORK_DELAY_MS = 50;

        private final String mPropertyName;
        private final int mAutoCorkDelayMs;
        private final Object mLock = new Object();
        @GuardedBy("mLock")
        private long mUncorkDeadlineMs = -1;  // SystemClock.uptimeMillis()
        @GuardedBy("mLock")
        private Handler mHandler;

        @GuardedBy("mLock")
        private NonceHandler mNonce;

        public AutoCorker(@NonNull String propertyName) {
            this(propertyName, DEFAULT_AUTO_CORK_DELAY_MS);
        }

        public AutoCorker(@NonNull String propertyName, int autoCorkDelayMs) {
            if (separatePermissionNotificationsEnabled()) {
                throw new IllegalStateException("AutoCorking is unavailable");
            }

            mPropertyName = propertyName;
            mAutoCorkDelayMs = autoCorkDelayMs;
            // We can't initialize mHandler here: when we're created, the main loop might not
            // be set up yet! Wait until we have a main loop to initialize our
            // corking callback.
        }

        public void autoCork() {
            synchronized (mLock) {
                if (mNonce == null) {
                    mNonce = getNonceHandler(mPropertyName);
                }
            }

            if (getLooper() == null) {
                // We're not ready to auto-cork yet, so just invalidate the cache immediately.
                if (DEBUG) {
                    Log.w(TAG, "invalidating instead of autocorking early in init: "
                            + mPropertyName);
                }
                mNonce.invalidate();
                return;
            }
            synchronized (mLock) {
                boolean alreadyQueued = mUncorkDeadlineMs >= 0;
                if (DEBUG) {
                    Log.d(TAG, formatSimple(
                            "autoCork %s mUncorkDeadlineMs=%s", mPropertyName,
                            mUncorkDeadlineMs));
                }
                mUncorkDeadlineMs = SystemClock.uptimeMillis() + mAutoCorkDelayMs;
                if (!alreadyQueued) {
                    getHandlerLocked().sendEmptyMessageAtTime(0, mUncorkDeadlineMs);
                    mNonce.cork();
                } else {
                    // Count this as a corked invalidation.
                    mNonce.invalidate();
                }
            }
        }

        private void handleMessage(Message msg) {
            synchronized (mLock) {
                if (DEBUG) {
                    Log.d(TAG, formatSimple(
                            "handleMsesage %s mUncorkDeadlineMs=%s",
                            mPropertyName, mUncorkDeadlineMs));
                }

                if (mUncorkDeadlineMs < 0) {
                    return;  // ???
                }
                long nowMs = SystemClock.uptimeMillis();
                if (mUncorkDeadlineMs > nowMs) {
                    mUncorkDeadlineMs = nowMs + mAutoCorkDelayMs;
                    if (DEBUG) {
                        Log.d(TAG, formatSimple(
                                        "scheduling uncork at %s",
                                        mUncorkDeadlineMs));
                    }
                    getHandlerLocked().sendEmptyMessageAtTime(0, mUncorkDeadlineMs);
                    return;
                }
                if (DEBUG) {
                    Log.d(TAG, "automatic uncorking " + mPropertyName);
                }
                mUncorkDeadlineMs = -1;
                mNonce.uncork();
            }
        }

        @GuardedBy("mLock")
        private Handler getHandlerLocked() {
            if (mHandler == null) {
                mHandler = new Handler(getLooper()) {
                        @Override
                        public void handleMessage(Message msg) {
                            AutoCorker.this.handleMessage(msg);
                        }
                    };
            }
            return mHandler;
        }

        /**
         * Return a looper for auto-uncork messages.  Messages should be processed on the
         * background thread, not on the main thread.
         */
        private static Looper getLooper() {
            return BackgroundThread.getHandler().getLooper();
        }
    }

    /**
     * Return the name of the cache, to be used in debug messages.  This is exposed
     * primarily for testing.
@@ -2243,7 +2031,6 @@ public class PropertyInvalidatedCache<Query, Result> {
            pw.println(formatSimple(
                "    Current Size: %d, Max Size: %d, HW Mark: %d, Overflows: %d",
                mCache.size(), mMaxEntries, mHighWaterMark, mMissOverflow));
            mCache.dump(pw);

            if (!brief) {
                if (isReservedNonce(mLastSeenNonce)) {
+0 −32
Original line number Diff line number Diff line
@@ -10,38 +10,6 @@ flag {
     bug: "360897450"
}

flag {
     namespace: "system_performance"
     name: "pic_isolate_cache_by_uid"
     is_fixed_read_only: true
     description: "Ensure that different UIDs use different caches"
     bug: "373752556"
}

flag {
     namespace: "system_performance"
     name: "pic_isolated_cache_statistics"
     is_fixed_read_only: true
     description: "Collects statistics for cache UID isolation strategies"
     bug: "379098894"
}

flag {
     namespace: "system_performance"
     name: "pic_separate_permission_notifications"
     is_fixed_read_only: true
     description: "Seperate PermissionManager notifications from cache udpates"
     bug: "379699402"
}

flag {
     namespace: "system_performance"
     name: "pic_cache_nulls"
     is_fixed_read_only: true
     description: "Cache null returns from binder calls"
     bug: "372923336"
}

flag {
     namespace: "system_performance"
     name: "pic_test_mode"
+1 −13
Original line number Diff line number Diff line
@@ -11886,25 +11886,13 @@ public abstract class PackageManager {
        sPackageInfoCache.uncorkInvalidations();
    }

    // This auto-corker is obsolete once the separate permission notifications feature is
    // committed.
    private static final PropertyInvalidatedCache.AutoCorker sCacheAutoCorker =
            PropertyInvalidatedCache.separatePermissionNotificationsEnabled()
            ? null
            : new PropertyInvalidatedCache
                    .AutoCorker(PermissionManager.CACHE_KEY_PACKAGE_INFO_CACHE);

    /**
     * Invalidate caches of package and permission information system-wide.
     *
     * @hide
     */
    public static void invalidatePackageInfoCache() {
        if (PropertyInvalidatedCache.separatePermissionNotificationsEnabled()) {
        sPackageInfoCache.invalidateCache();
        } else {
            sCacheAutoCorker.autoCork();
        }
    }

    /**
+0 −3
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.app;

import static android.app.Flags.FLAG_PIC_ISOLATE_CACHE_BY_UID;
import static android.app.PropertyInvalidatedCache.NONCE_UNSET;
import static android.app.PropertyInvalidatedCache.MODULE_ADSERVICES;
import static android.app.PropertyInvalidatedCache.MODULE_BLUETOOTH;
@@ -39,7 +38,6 @@ import android.app.PropertyInvalidatedCache.NonceStore;
import android.app.PropertyInvalidatedCache.NonceWatcher;
import android.os.Binder;
import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;

@@ -667,7 +665,6 @@ public class PropertyInvalidatedCacheTests {
    }

    // Verify that a cache created with isolatedUids(true) separates out the results.
    @RequiresFlagsEnabled(FLAG_PIC_ISOLATE_CACHE_BY_UID)
    @Test
    public void testIsolatedUids() {
        TestCache cache = new TestCache(new Args(MODULE_TEST)
+0 −14
Original line number Diff line number Diff line
@@ -16,27 +16,17 @@

package android.os;

import static android.app.Flags.FLAG_PIC_ISOLATE_CACHE_BY_UID;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.app.PropertyInvalidatedCache;
import android.app.PropertyInvalidatedCache.Args;
import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.ravenwood.RavenwoodRule;
import android.os.IpcDataCache;

import androidx.test.filters.SmallTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

/**
@@ -51,10 +41,6 @@ import org.junit.Test;
@SmallTest
public class IpcDataCacheTest {

    @Rule
    public final CheckFlagsRule mCheckFlagsRule =
            DeviceFlagsValueProvider.createCheckFlagsRule();

    // Configuration for creating caches
    private static final String MODULE = IpcDataCache.MODULE_TEST;
    private static final String API = "testApi";