blob: 0850916ccbe5752e8d98acf3ea27d4cf20c3c1ea [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package android.testing;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.database.ContentObserver;
import android.net.Uri;
import android.util.ArraySet;
import com.google.android.collect.Maps;
import java.util.Map;
/**
* A version of ContentResolver that allows easy mocking of providers.
* By default it acts as a normal ContentResolver and returns all the
* same providers.
* @see #addProvider(String, ContentProvider)
* @see #setFallbackToExisting(boolean)
*/
public class TestableContentResolver extends ContentResolver {
private final Map<String, ContentProvider> mProviders = Maps.newHashMap();
private final ContentResolver mParent;
private final ArraySet<ContentProvider> mInUse = new ArraySet<>();
private boolean mFallbackToExisting;
public TestableContentResolver(Context context) {
super(context);
mParent = context.getContentResolver();
mFallbackToExisting = true;
}
/**
* Sets whether existing providers should be returned when a mock does not exist.
* The default is true.
*/
public void setFallbackToExisting(boolean fallbackToExisting) {
mFallbackToExisting = fallbackToExisting;
}
/**
* Adds access to a provider based on its authority
*
* @param name The authority name associated with the provider.
* @param provider An instance of {@link android.content.ContentProvider} or one of its
* subclasses, or null.
*/
public void addProvider(String name, ContentProvider provider) {
mProviders.put(name, provider);
}
@Override
protected IContentProvider acquireProvider(Context context, String name) {
final ContentProvider provider = mProviders.get(name);
if (provider != null) {
return provider.getIContentProvider();
} else {
return mFallbackToExisting ? mParent.acquireProvider(name) : null;
}
}
@Override
protected IContentProvider acquireExistingProvider(Context context, String name) {
final ContentProvider provider = mProviders.get(name);
if (provider != null) {
return provider.getIContentProvider();
} else {
return mFallbackToExisting ? mParent.acquireExistingProvider(
new Uri.Builder().authority(name).build()) : null;
}
}
@Override
public boolean releaseProvider(IContentProvider provider) {
if (!mFallbackToExisting) return true;
if (mInUse.contains(provider)) {
mInUse.remove(provider);
return true;
}
return mParent.releaseProvider(provider);
}
@Override
protected IContentProvider acquireUnstableProvider(Context c, String name) {
final ContentProvider provider = mProviders.get(name);
if (provider != null) {
return provider.getIContentProvider();
} else {
return mFallbackToExisting ? mParent.acquireUnstableProvider(name) : null;
}
}
@Override
public boolean releaseUnstableProvider(IContentProvider icp) {
if (!mFallbackToExisting) return true;
if (mInUse.contains(icp)) {
mInUse.remove(icp);
return true;
}
return mParent.releaseUnstableProvider(icp);
}
@Override
public void unstableProviderDied(IContentProvider icp) {
if (!mFallbackToExisting) return;
if (mInUse.contains(icp)) {
return;
}
mParent.unstableProviderDied(icp);
}
@Override
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
if (!mFallbackToExisting) return;
if (!mProviders.containsKey(uri.getAuthority())) {
super.notifyChange(uri, observer, syncToNetwork);
}
}
}