blob: 0850916ccbe5752e8d98acf3ea27d4cf20c3c1ea [file] [log] [blame]
Jason Monke9789282016-11-09 08:59:56 -05001/*
Jason Monk340b0e52017-03-08 14:57:56 -05002 * Copyright (C) 2017 The Android Open Source Project
Jason Monke9789282016-11-09 08:59:56 -05003 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
Jason Monk340b0e52017-03-08 14:57:56 -050015package android.testing;
Jason Monke9789282016-11-09 08:59:56 -050016
17import android.content.ContentProvider;
18import android.content.ContentResolver;
19import android.content.Context;
20import android.content.IContentProvider;
21import android.database.ContentObserver;
22import android.net.Uri;
23import android.util.ArraySet;
24
25import com.google.android.collect.Maps;
26
27import java.util.Map;
28
29/**
Jason Monk0c408002017-05-03 15:43:52 -040030 * A version of ContentResolver that allows easy mocking of providers.
31 * By default it acts as a normal ContentResolver and returns all the
32 * same providers.
33 * @see #addProvider(String, ContentProvider)
34 * @see #setFallbackToExisting(boolean)
Jason Monke9789282016-11-09 08:59:56 -050035 */
Jason Monk340b0e52017-03-08 14:57:56 -050036public class TestableContentResolver extends ContentResolver {
Jason Monke9789282016-11-09 08:59:56 -050037
38 private final Map<String, ContentProvider> mProviders = Maps.newHashMap();
39 private final ContentResolver mParent;
40 private final ArraySet<ContentProvider> mInUse = new ArraySet<>();
41 private boolean mFallbackToExisting;
42
Jason Monk340b0e52017-03-08 14:57:56 -050043 public TestableContentResolver(Context context) {
Jason Monke9789282016-11-09 08:59:56 -050044 super(context);
45 mParent = context.getContentResolver();
46 mFallbackToExisting = true;
47 }
48
49 /**
50 * Sets whether existing providers should be returned when a mock does not exist.
51 * The default is true.
52 */
53 public void setFallbackToExisting(boolean fallbackToExisting) {
54 mFallbackToExisting = fallbackToExisting;
55 }
56
57 /**
58 * Adds access to a provider based on its authority
59 *
60 * @param name The authority name associated with the provider.
61 * @param provider An instance of {@link android.content.ContentProvider} or one of its
62 * subclasses, or null.
63 */
64 public void addProvider(String name, ContentProvider provider) {
65 mProviders.put(name, provider);
66 }
67
68 @Override
69 protected IContentProvider acquireProvider(Context context, String name) {
70 final ContentProvider provider = mProviders.get(name);
71 if (provider != null) {
72 return provider.getIContentProvider();
73 } else {
74 return mFallbackToExisting ? mParent.acquireProvider(name) : null;
75 }
76 }
77
78 @Override
79 protected IContentProvider acquireExistingProvider(Context context, String name) {
80 final ContentProvider provider = mProviders.get(name);
81 if (provider != null) {
82 return provider.getIContentProvider();
83 } else {
84 return mFallbackToExisting ? mParent.acquireExistingProvider(
85 new Uri.Builder().authority(name).build()) : null;
86 }
87 }
88
89 @Override
90 public boolean releaseProvider(IContentProvider provider) {
91 if (!mFallbackToExisting) return true;
92 if (mInUse.contains(provider)) {
93 mInUse.remove(provider);
94 return true;
95 }
96 return mParent.releaseProvider(provider);
97 }
98
99 @Override
100 protected IContentProvider acquireUnstableProvider(Context c, String name) {
101 final ContentProvider provider = mProviders.get(name);
102 if (provider != null) {
103 return provider.getIContentProvider();
104 } else {
105 return mFallbackToExisting ? mParent.acquireUnstableProvider(name) : null;
106 }
107 }
108
109 @Override
110 public boolean releaseUnstableProvider(IContentProvider icp) {
111 if (!mFallbackToExisting) return true;
112 if (mInUse.contains(icp)) {
113 mInUse.remove(icp);
114 return true;
115 }
116 return mParent.releaseUnstableProvider(icp);
117 }
118
119 @Override
120 public void unstableProviderDied(IContentProvider icp) {
121 if (!mFallbackToExisting) return;
122 if (mInUse.contains(icp)) {
123 return;
124 }
125 mParent.unstableProviderDied(icp);
126 }
127
128 @Override
129 public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
130 if (!mFallbackToExisting) return;
131 if (!mProviders.containsKey(uri.getAuthority())) {
132 super.notifyChange(uri, observer, syncToNetwork);
133 }
134 }
135}