Merge "Fix RootsCache invalidation bugs." into nyc-dev

This commit is contained in:
Jeff Sharkey
2016-03-31 00:27:20 +00:00
committed by Android (Google) Code Review
4 changed files with 37 additions and 47 deletions

View File

@@ -16,7 +16,7 @@
package android.util;
import libcore.util.Objects;
import java.util.Objects;
/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
@@ -52,7 +52,7 @@ public class Pair<F, S> {
return false;
}
Pair<?, ?> p = (Pair<?, ?>) o;
return Objects.equal(p.first, first) && Objects.equal(p.second, second);
return Objects.equals(p.first, first) && Objects.equals(p.second, second);
}
/**
@@ -65,6 +65,11 @@ public class Pair<F, S> {
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
}
@Override
public String toString() {
return "Pair{" + String.valueOf(first) + " " + String.valueOf(second) + "}";
}
/**
* Convenience method for creating an appropriately typed pair.
* @param a the first object in the Pair

View File

@@ -65,8 +65,6 @@ public class RootsCache {
private static final String TAG = "RootsCache";
private static final boolean ENABLE_SYSTEM_CACHE = true;
private final Context mContext;
private final ContentObserver mObserver;
private OnCacheUpdateListener mCacheUpdateListener;
@@ -200,7 +198,7 @@ public class RootsCache {
synchronized (mLock) {
for (String authority : mStoppedAuthorities) {
if (DEBUG) Log.d(TAG, "Loading stopped authority " + authority);
mRoots.putAll(authority, loadRootsForAuthority(resolver, authority));
mRoots.putAll(authority, loadRootsForAuthority(resolver, authority, true));
}
mStoppedAuthorities.clear();
}
@@ -219,13 +217,13 @@ public class RootsCache {
if (DEBUG) {
Log.d(TAG, "Loading stopped authority " + authority);
}
mRoots.putAll(authority, loadRootsForAuthority(resolver, authority));
mRoots.putAll(authority, loadRootsForAuthority(resolver, authority, true));
mStoppedAuthorities.remove(authority);
}
}
private class UpdateTask extends AsyncTask<Void, Void, Void> {
private final String mFilterPackage;
private final String mForceRefreshPackage;
private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
private final HashSet<String> mTaskStoppedAuthorities = new HashSet<>();
@@ -238,18 +236,18 @@ public class RootsCache {
}
/**
* Only update roots belonging to given package name. Other roots will
* Force update roots belonging to given package name. Other roots will
* be copied from cached {@link #mRoots} values.
*/
public UpdateTask(String filterPackage) {
mFilterPackage = filterPackage;
public UpdateTask(String forceRefreshPackage) {
mForceRefreshPackage = forceRefreshPackage;
}
@Override
protected Void doInBackground(Void... params) {
final long start = SystemClock.elapsedRealtime();
if (mFilterPackage != null) {
if (mForceRefreshPackage != null) {
// We must have previously cached values to fill in non-matching
// packages, so wait around for successful first load.
if (!waitForFirstLoad()) {
@@ -302,29 +300,17 @@ public class RootsCache {
return;
}
// Try using cached roots if filtering
boolean cacheHit = false;
if (mFilterPackage != null && !mFilterPackage.equals(info.packageName)) {
synchronized (mLock) {
if (mTaskRoots.putAll(info.authority, mRoots.get(info.authority))) {
if (DEBUG) Log.d(TAG, "Used cached roots for " + info.authority);
cacheHit = true;
}
}
}
// Cache miss, or loading everything
if (!cacheHit) {
mTaskRoots.putAll(info.authority,
loadRootsForAuthority(mContext.getContentResolver(), info.authority));
}
final boolean forceRefresh = Objects.equals(mForceRefreshPackage, info.packageName);
mTaskRoots.putAll(info.authority, loadRootsForAuthority(mContext.getContentResolver(),
info.authority, forceRefresh));
}
}
/**
* Bring up requested provider and query for all active roots.
*/
private Collection<RootInfo> loadRootsForAuthority(ContentResolver resolver, String authority) {
private Collection<RootInfo> loadRootsForAuthority(ContentResolver resolver, String authority,
boolean forceRefresh) {
if (DEBUG) Log.d(TAG, "Loading roots for " + authority);
synchronized (mObservedAuthorities) {
@@ -336,7 +322,7 @@ public class RootsCache {
}
final Uri rootsUri = DocumentsContract.buildRootsUri(authority);
if (ENABLE_SYSTEM_CACHE) {
if (!forceRefresh) {
// Look for roots data that we might have cached for ourselves in the
// long-lived system process.
final Bundle systemCache = resolver.getCache(rootsUri);
@@ -363,14 +349,12 @@ public class RootsCache {
ContentProviderClient.releaseQuietly(client);
}
if (ENABLE_SYSTEM_CACHE) {
// Cache these freshly parsed roots over in the long-lived system
// process, in case our process goes away. The system takes care of
// invalidating the cache if the package or Uri changes.
final Bundle systemCache = new Bundle();
systemCache.putParcelableArrayList(TAG, roots);
resolver.putCache(rootsUri, systemCache);
}
// Cache these freshly parsed roots over in the long-lived system
// process, in case our process goes away. The system takes care of
// invalidating the cache if the package or Uri changes.
final Bundle systemCache = new Bundle();
systemCache.putParcelableArrayList(TAG, roots);
resolver.putCache(rootsUri, systemCache);
return roots;
}
@@ -384,8 +368,8 @@ public class RootsCache {
synchronized (mLock) {
RootInfo root = getRootLocked(authority, rootId);
if (root == null) {
mRoots.putAll(
authority, loadRootsForAuthority(mContext.getContentResolver(), authority));
mRoots.putAll(authority,
loadRootsForAuthority(mContext.getContentResolver(), authority, false));
root = getRootLocked(authority, rootId);
}
return root;

View File

@@ -1231,7 +1231,8 @@ class MountService extends IMountService.Stub
}
final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
@@ -1347,7 +1348,8 @@ class MountService extends IMountService.Stub
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
}

View File

@@ -26,9 +26,9 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentService;
import android.content.ISyncStatusObserver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ISyncStatusObserver;
import android.content.PeriodicSync;
import android.content.SyncAdapterType;
import android.content.SyncInfo;
@@ -58,18 +58,15 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
/**
* {@hide}
@@ -1030,14 +1027,16 @@ public final class ContentService extends IContentService.Stub {
if (uri != null) {
for (int i = 0; i < packageCache.size();) {
final Uri key = packageCache.keyAt(i).second;
if (Objects.equals(key, uri)) {
final Pair<String, Uri> key = packageCache.keyAt(i);
if (key.second != null && key.second.toString().startsWith(uri.toString())) {
Slog.d(TAG, "Invalidating cache for key " + key);
packageCache.removeAt(i);
} else {
i++;
}
}
} else {
Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
packageCache.clear();
}
}