Loading core/java/android/app/PropertyInvalidatedCache.java +3 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; Loading Loading @@ -2394,9 +2393,11 @@ public class PropertyInvalidatedCache<Query, Result> { * provided {@link PrintWriter}. Optional switches allow the caller to choose * specific caches (selection is by cache name or property name); if these switches * are used then the output includes both cache statistics and cache entries. * @hide */ @VisibleForTesting @NeverCompile private static void dumpCacheInfo(@NonNull PrintWriter pw, @NonNull String[] args) { public static void dumpCacheInfo(@NonNull PrintWriter pw, @NonNull String[] args) { if (!sEnabled) { pw.println(" Caching is disabled in this process."); return; Loading core/java/android/os/IpcDataCache.java +1 −17 Original line number Diff line number Diff line Loading @@ -24,26 +24,10 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.PropertyInvalidatedCache; import android.app.PropertyInvalidatedCache.Args; import android.text.TextUtils; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FastPrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicLong; /** * LRU cache that's invalidated when an opaque value in a property changes. Self-synchronizing, Loading Loading @@ -411,7 +395,7 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, * 1. Instance-per-cache: create a static instance of this class using the same * parameters as would have been given to IpcDataCache (or * PropertyInvalidatedCache). This static instance provides a hook for the * invalidateCache() and disableForLocalProcess() calls, which, generally, must * invalidateCache() and disableForCurrentProcess() calls, which, generally, must * also be static. * * 2. Short-hand for shared configuration parameters: create an instance of this class Loading core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java +79 −5 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM; import static android.app.PropertyInvalidatedCache.MODULE_TEST; import static android.app.PropertyInvalidatedCache.NonceStore.INVALID_NONCE_INDEX; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; Loading @@ -33,17 +35,13 @@ import static org.junit.Assert.fail; import android.annotation.SuppressLint; import android.app.PropertyInvalidatedCache.Args; import android.app.PropertyInvalidatedCache.NonceWatcher; import android.app.PropertyInvalidatedCache.NonceStore; import android.app.PropertyInvalidatedCache.NonceWatcher; import android.os.Binder; import android.util.Log; import com.android.internal.os.ApplicationSharedMemory; 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 androidx.test.filters.SmallTest; Loading @@ -54,6 +52,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.util.concurrent.TimeUnit; /** Loading Loading @@ -800,4 +800,78 @@ public class PropertyInvalidatedCacheTests { // The recompute is 4 because nulls were not cached. assertEquals(4, cache.getRecomputeCount()); } // Collect the dumpsys output. The boolean is for brief output. private static String getDumpsys(boolean brief) { final String[] args; if (brief) { args = new String[] { "-brief" }; } else { args = new String[0]; } ByteArrayOutputStream barray = new ByteArrayOutputStream(); PrintWriter bout = new PrintWriter(barray); PropertyInvalidatedCache.dumpCacheInfo(bout, args); bout.close(); return barray.toString(); } @Test public void testDumpsysCacheinfo() { // Construct one well-known cache. TestCache cache = new TestCache(new Args(MODULE_TEST) .maxEntries(4).api("testDumpsys").cacheNulls(true), new TestQuery()); cache.invalidateCache(); String dump = getDumpsys(/* brief */ false); String p; // Test of the test. If this test fails, it is likely that the dumpsys is badly broken. p = "Cache-key:"; assertThat(dump).containsMatch(p); // Test of the test: this should fail. This is not a functional test: if this test passes // then the logic in this test routine is faulty. p = "Cache-key: +notACache\\R +invalidated:1"; assertThat(dump).doesNotContainMatch(p); // Verify that there is a handler for test/testDumpsys and it has one invalidation. p = "Cache-key: +test/testDumpsys\\R +invalidated:1"; assertThat(dump).containsMatch(p); // Verify that the testDumpsys cache is present. It has zero hits, misses, and clears. p = "Cache Name: testDumpsys\\R +Key: test/testDumpsys\\R" + " +Hits: 0, Misses: 0, Skips: 0"; assertThat(dump).containsMatch(p); // Verify that the well-known cache getApplicationInfo is present. p = "Cache Name: getApplicationInfo"; assertThat(dump).containsMatch(p); // Construct a brief listing. dump = getDumpsys(/* brief */ true); // Verify that there is a handler for test/testDumpsys and it has one invalidation. p = "Cache-key: +test/testDumpsys\\R +invalidated:1"; assertThat(dump).containsMatch(p); // Verify that the testDumpsys cache is present. It has zero hits, misses, and clears. p = "Cache Name: testDumpsys"; assertThat(dump).doesNotContainMatch(p); // Add some activity. Two misses and one hit. cache.query(1); cache.query(2); cache.query(1); // Construct a brief listing. dump = getDumpsys(/* brief */ true); // Verify that testDumpsys cache is present and it has the expected attributes. p = "Cache Name: testDumpsys\\R +Key: test/testDumpsys\\R" + " +Hits: 1, Misses: 2, Skips: 0"; assertThat(dump).containsMatch(p); } } Loading
core/java/android/app/PropertyInvalidatedCache.java +3 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; Loading Loading @@ -2394,9 +2393,11 @@ public class PropertyInvalidatedCache<Query, Result> { * provided {@link PrintWriter}. Optional switches allow the caller to choose * specific caches (selection is by cache name or property name); if these switches * are used then the output includes both cache statistics and cache entries. * @hide */ @VisibleForTesting @NeverCompile private static void dumpCacheInfo(@NonNull PrintWriter pw, @NonNull String[] args) { public static void dumpCacheInfo(@NonNull PrintWriter pw, @NonNull String[] args) { if (!sEnabled) { pw.println(" Caching is disabled in this process."); return; Loading
core/java/android/os/IpcDataCache.java +1 −17 Original line number Diff line number Diff line Loading @@ -24,26 +24,10 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.PropertyInvalidatedCache; import android.app.PropertyInvalidatedCache.Args; import android.text.TextUtils; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FastPrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicLong; /** * LRU cache that's invalidated when an opaque value in a property changes. Self-synchronizing, Loading Loading @@ -411,7 +395,7 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, * 1. Instance-per-cache: create a static instance of this class using the same * parameters as would have been given to IpcDataCache (or * PropertyInvalidatedCache). This static instance provides a hook for the * invalidateCache() and disableForLocalProcess() calls, which, generally, must * invalidateCache() and disableForCurrentProcess() calls, which, generally, must * also be static. * * 2. Short-hand for shared configuration parameters: create an instance of this class Loading
core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java +79 −5 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM; import static android.app.PropertyInvalidatedCache.MODULE_TEST; import static android.app.PropertyInvalidatedCache.NonceStore.INVALID_NONCE_INDEX; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; Loading @@ -33,17 +35,13 @@ import static org.junit.Assert.fail; import android.annotation.SuppressLint; import android.app.PropertyInvalidatedCache.Args; import android.app.PropertyInvalidatedCache.NonceWatcher; import android.app.PropertyInvalidatedCache.NonceStore; import android.app.PropertyInvalidatedCache.NonceWatcher; import android.os.Binder; import android.util.Log; import com.android.internal.os.ApplicationSharedMemory; 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 androidx.test.filters.SmallTest; Loading @@ -54,6 +52,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.util.concurrent.TimeUnit; /** Loading Loading @@ -800,4 +800,78 @@ public class PropertyInvalidatedCacheTests { // The recompute is 4 because nulls were not cached. assertEquals(4, cache.getRecomputeCount()); } // Collect the dumpsys output. The boolean is for brief output. private static String getDumpsys(boolean brief) { final String[] args; if (brief) { args = new String[] { "-brief" }; } else { args = new String[0]; } ByteArrayOutputStream barray = new ByteArrayOutputStream(); PrintWriter bout = new PrintWriter(barray); PropertyInvalidatedCache.dumpCacheInfo(bout, args); bout.close(); return barray.toString(); } @Test public void testDumpsysCacheinfo() { // Construct one well-known cache. TestCache cache = new TestCache(new Args(MODULE_TEST) .maxEntries(4).api("testDumpsys").cacheNulls(true), new TestQuery()); cache.invalidateCache(); String dump = getDumpsys(/* brief */ false); String p; // Test of the test. If this test fails, it is likely that the dumpsys is badly broken. p = "Cache-key:"; assertThat(dump).containsMatch(p); // Test of the test: this should fail. This is not a functional test: if this test passes // then the logic in this test routine is faulty. p = "Cache-key: +notACache\\R +invalidated:1"; assertThat(dump).doesNotContainMatch(p); // Verify that there is a handler for test/testDumpsys and it has one invalidation. p = "Cache-key: +test/testDumpsys\\R +invalidated:1"; assertThat(dump).containsMatch(p); // Verify that the testDumpsys cache is present. It has zero hits, misses, and clears. p = "Cache Name: testDumpsys\\R +Key: test/testDumpsys\\R" + " +Hits: 0, Misses: 0, Skips: 0"; assertThat(dump).containsMatch(p); // Verify that the well-known cache getApplicationInfo is present. p = "Cache Name: getApplicationInfo"; assertThat(dump).containsMatch(p); // Construct a brief listing. dump = getDumpsys(/* brief */ true); // Verify that there is a handler for test/testDumpsys and it has one invalidation. p = "Cache-key: +test/testDumpsys\\R +invalidated:1"; assertThat(dump).containsMatch(p); // Verify that the testDumpsys cache is present. It has zero hits, misses, and clears. p = "Cache Name: testDumpsys"; assertThat(dump).doesNotContainMatch(p); // Add some activity. Two misses and one hit. cache.query(1); cache.query(2); cache.query(1); // Construct a brief listing. dump = getDumpsys(/* brief */ true); // Verify that testDumpsys cache is present and it has the expected attributes. p = "Cache Name: testDumpsys\\R +Key: test/testDumpsys\\R" + " +Hits: 1, Misses: 2, Skips: 0"; assertThat(dump).containsMatch(p); } }