summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorCollin Fijalkovich <cfijalkovich@google.com>2020-04-29 16:02:07 -0700
committerCollin Fijalkovich <cfijalkovich@google.com>2020-05-13 11:15:22 -0700
commitceefcec397fedca948ab7a710e42ec635591f9b2 (patch)
tree5b3ac105f046b40179b53b93d9ca3cdc13541a6e /core/java
parent8c239da8d54bc2ac93fe666a7ca7825f0e82b923 (diff)
Add cache debugging information to bugreports.
Following the model for dumpsys gfxinfo, this patchset adds a CacheBinder service that dumps cache state information from each process. Bug: 153661880 Test: adb shell dumpsys cacheinfo Test: adb bugreport Change-Id: Ie7cce70e56777a200e3e3e92ab895126b6f29032
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/ActivityThread.java6
-rw-r--r--core/java/android/app/IApplicationThread.aidl1
-rw-r--r--core/java/android/app/PropertyInvalidatedCache.java88
3 files changed, 94 insertions, 1 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c6e2d5290d2e..ab82eb026b51 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1538,6 +1538,12 @@ public final class ActivityThread extends ClientTransactionHandler {
IoUtils.closeQuietly(pfd);
}
+ @Override
+ public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
+ PropertyInvalidatedCache.dumpCacheInfo(pfd.getFileDescriptor(), args);
+ IoUtils.closeQuietly(pfd);
+ }
+
private File getDatabasesDir(Context context) {
// There's no simple way to get the databases/ path, so do it this way.
return context.getDatabasePath("a").getParentFile();
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 1f6e4cac199a..6e9157e2a8c3 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -119,6 +119,7 @@ oneway interface IApplicationThread {
boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
in String[] args);
void dumpGfxInfo(in ParcelFileDescriptor fd, in String[] args);
+ void dumpCacheInfo(in ParcelFileDescriptor fd, in String[] args);
void dumpProvider(in ParcelFileDescriptor fd, IBinder servicetoken,
in String[] args);
void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args);
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 58705434f774..01cf2b94a842 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -26,13 +26,19 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastPrintWriter;
+import java.io.FileDescriptor;
+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;
@@ -235,6 +241,11 @@ public abstract class PropertyInvalidatedCache<Query, Result> {
private boolean mDisabled = false;
/**
+ * Maximum number of entries the cache will maintain.
+ */
+ private final int mMaxEntries;
+
+ /**
* Make a new property invalidated cache.
*
* @param maxEntries Maximum number of entries to cache; LRU discard
@@ -242,6 +253,7 @@ public abstract class PropertyInvalidatedCache<Query, Result> {
*/
public PropertyInvalidatedCache(int maxEntries, @NonNull String propertyName) {
mPropertyName = propertyName;
+ mMaxEntries = maxEntries;
mCache = new LinkedHashMap<Query, Result>(
2 /* start small */,
0.75f /* default load factor */,
@@ -728,11 +740,85 @@ public abstract class PropertyInvalidatedCache<Query, Result> {
}
/**
- * Return a list of caches alive at the current time.
+ * Returns a list of caches alive at the current time.
*/
public static ArrayList<PropertyInvalidatedCache> getActiveCaches() {
synchronized (sCorkLock) {
return new ArrayList<PropertyInvalidatedCache>(sCaches.keySet());
}
}
+
+ /**
+ * Returns a list of the active corks in a process.
+ */
+ public static ArrayList<Map.Entry<String, Integer>> getActiveCorks() {
+ synchronized (sCorkLock) {
+ return new ArrayList<Map.Entry<String, Integer>>(sCorks.entrySet());
+ }
+ }
+
+ private void dumpContents(PrintWriter pw, String[] args) {
+ synchronized (mLock) {
+ pw.println(String.format(" Cache Property Name: %s", cacheName()));
+ pw.println(String.format(" Last Observed Nonce: %d", mLastSeenNonce));
+ pw.println(String.format(" Current Size: %d, Max Size: %d",
+ mCache.entrySet().size(), mMaxEntries));
+ pw.println(String.format(" Enabled: %s", mDisabled ? "false" : "true"));
+
+ Set<Map.Entry<Query, Result>> cacheEntries = mCache.entrySet();
+ if (cacheEntries.size() == 0) {
+ pw.println("");
+ return;
+ }
+
+ pw.println("");
+ pw.println(" Contents:");
+ for (Map.Entry<Query, Result> entry : cacheEntries) {
+ String key = Objects.toString(entry.getKey());
+ String value = Objects.toString(entry.getValue());
+
+ pw.println(String.format(" Key: %s\n Value: %s\n", key, value));
+ }
+ }
+ }
+
+ /**
+ * Dumps contents of every cache in the process to the provided FileDescriptor.
+ */
+ public static void dumpCacheInfo(FileDescriptor fd, String[] args) {
+ ArrayList<PropertyInvalidatedCache> activeCaches;
+ ArrayList<Map.Entry<String, Integer>> activeCorks;
+
+ try (
+ FileOutputStream fout = new FileOutputStream(fd);
+ PrintWriter pw = new FastPrintWriter(fout);
+ ) {
+ if (!sEnabled) {
+ pw.println(" Caching is disabled in this process.");
+ return;
+ }
+
+ synchronized (sCorkLock) {
+ activeCaches = getActiveCaches();
+ activeCorks = getActiveCorks();
+
+ if (activeCorks.size() > 0) {
+ pw.println(" Corking Status:");
+ for (int i = 0; i < activeCorks.size(); i++) {
+ Map.Entry<String, Integer> entry = activeCorks.get(i);
+ pw.println(String.format(" Property Name: %s Count: %d",
+ entry.getKey(), entry.getValue()));
+ }
+ }
+ }
+
+ for (int i = 0; i < activeCaches.size(); i++) {
+ PropertyInvalidatedCache currentCache = activeCaches.get(i);
+ currentCache.dumpContents(pw, args);
+ pw.flush();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to dump PropertyInvalidatedCache instances");
+ }
+ }
}