1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.test.mock;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.ContentProvider;
22 import android.content.ContentProviderOperation;
23 import android.content.ContentProviderResult;
24 import android.content.ContentResolver;
25 import android.content.ContentValues;
26 import android.content.Context;
27 import android.content.IContentProvider;
28 import android.content.Intent;
29 import android.content.OperationApplicationException;
30 import android.content.pm.PathPermission;
31 import android.content.pm.ProviderInfo;
32 import android.content.res.AssetFileDescriptor;
33 import android.database.Cursor;
34 import android.net.Uri;
35 import android.os.AsyncTask;
36 import android.os.Bundle;
37 import android.os.IBinder;
38 import android.os.ICancellationSignal;
39 import android.os.ParcelFileDescriptor;
40 import android.os.RemoteCallback;
41 import android.os.RemoteException;
42 
43 import java.io.FileNotFoundException;
44 import java.util.ArrayList;
45 
46 /**
47  * Mock implementation of ContentProvider.  All methods are non-functional and throw
48  * {@link java.lang.UnsupportedOperationException}.  Tests can extend this class to
49  * implement behavior needed for tests.
50  */
51 public class MockContentProvider extends ContentProvider {
52     /*
53      * Note: if you add methods to ContentProvider, you must add similar methods to
54      *       MockContentProvider.
55      */
56 
57     /**
58      * IContentProvider that directs all calls to this MockContentProvider.
59      */
60     private class InversionIContentProvider implements IContentProvider {
61         @Override
applyBatch(String callingPackage, @Nullable String featureId, String authority, ArrayList<ContentProviderOperation> operations)62         public ContentProviderResult[] applyBatch(String callingPackage,
63                 @Nullable String featureId, String authority,
64                 ArrayList<ContentProviderOperation> operations)
65                 throws RemoteException, OperationApplicationException {
66             return MockContentProvider.this.applyBatch(authority, operations);
67         }
68 
69         @Override
bulkInsert(String callingPackage, @Nullable String featureId, Uri url, ContentValues[] initialValues)70         public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
71                 ContentValues[] initialValues) throws RemoteException {
72             return MockContentProvider.this.bulkInsert(url, initialValues);
73         }
74 
75         @Override
delete(String callingPackage, @Nullable String featureId, Uri url, Bundle extras)76         public int delete(String callingPackage, @Nullable String featureId, Uri url,
77                 Bundle extras) throws RemoteException {
78             return MockContentProvider.this.delete(url, extras);
79         }
80 
81         @Override
getType(Uri url)82         public String getType(Uri url) throws RemoteException {
83             return MockContentProvider.this.getType(url);
84         }
85 
86         @Override
getTypeAsync(Uri uri, RemoteCallback callback)87         public void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException {
88             MockContentProvider.this.getTypeAsync(uri, callback);
89         }
90 
91         @Override
insert(String callingPackage, @Nullable String featureId, Uri url, ContentValues initialValues, Bundle extras)92         public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
93                 ContentValues initialValues, Bundle extras) throws RemoteException {
94             return MockContentProvider.this.insert(url, initialValues, extras);
95         }
96 
97         @Override
openAssetFile(String callingPackage, @Nullable String featureId, Uri url, String mode, ICancellationSignal signal)98         public AssetFileDescriptor openAssetFile(String callingPackage,
99                 @Nullable String featureId, Uri url, String mode, ICancellationSignal signal)
100                 throws RemoteException, FileNotFoundException {
101             return MockContentProvider.this.openAssetFile(url, mode);
102         }
103 
104         @Override
openFile(String callingPackage, @Nullable String featureId, Uri url, String mode, ICancellationSignal signal, IBinder callerToken)105         public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
106                 Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
107                 throws RemoteException, FileNotFoundException {
108             return MockContentProvider.this.openFile(url, mode);
109         }
110 
111         @Override
query(String callingPackage, @Nullable String featureId, Uri url, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)112         public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
113                 @Nullable String[] projection, @Nullable Bundle queryArgs,
114                 @Nullable ICancellationSignal cancellationSignal) throws RemoteException {
115             return MockContentProvider.this.query(url, projection, queryArgs, null);
116         }
117 
118         @Override
update(String callingPackage, @Nullable String featureId, Uri url, ContentValues values, Bundle extras)119         public int update(String callingPackage, @Nullable String featureId, Uri url,
120                 ContentValues values, Bundle extras) throws RemoteException {
121             return MockContentProvider.this.update(url, values, extras);
122         }
123 
124         @Override
call(String callingPackage, @Nullable String featureId, String authority, String method, String request, Bundle args)125         public Bundle call(String callingPackage, @Nullable String featureId, String authority,
126                 String method, String request, Bundle args) throws RemoteException {
127             return MockContentProvider.this.call(authority, method, request, args);
128         }
129 
130         @Override
asBinder()131         public IBinder asBinder() {
132             return MockContentProvider.this.getIContentProviderBinder();
133         }
134 
135         @Override
getStreamTypes(Uri url, String mimeTypeFilter)136         public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
137             return MockContentProvider.this.getStreamTypes(url, mimeTypeFilter);
138         }
139 
140         @Override
openTypedAssetFile(String callingPackage, @Nullable String featureId, Uri url, String mimeType, Bundle opts, ICancellationSignal signal)141         public AssetFileDescriptor openTypedAssetFile(String callingPackage,
142                 @Nullable String featureId, Uri url, String mimeType, Bundle opts,
143                 ICancellationSignal signal) throws RemoteException, FileNotFoundException {
144             return MockContentProvider.this.openTypedAssetFile(url, mimeType, opts);
145         }
146 
147         @Override
createCancellationSignal()148         public ICancellationSignal createCancellationSignal() throws RemoteException {
149             return null;
150         }
151 
152         @Override
canonicalize(String callingPkg, @Nullable String featureId, Uri uri)153         public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
154                 throws RemoteException {
155             return MockContentProvider.this.canonicalize(uri);
156         }
157 
158         @Override
canonicalizeAsync(String callingPkg, String featureId, Uri uri, RemoteCallback callback)159         public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
160                 RemoteCallback callback) {
161             MockContentProvider.this.canonicalizeAsync(uri, callback);
162         }
163 
164         @Override
uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)165         public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
166                 throws RemoteException {
167             return MockContentProvider.this.uncanonicalize(uri);
168         }
169 
170         @Override
refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args, ICancellationSignal cancellationSignal)171         public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
172                 Bundle args, ICancellationSignal cancellationSignal) throws RemoteException {
173             return MockContentProvider.this.refresh(url, args);
174         }
175 
176         @Override
checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid, int modeFlags)177         public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri,
178                 int uid, int modeFlags) {
179             return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags);
180         }
181     }
182     private final InversionIContentProvider mIContentProvider = new InversionIContentProvider();
183 
184     /**
185      * A constructor using {@link MockContext} instance as a Context in it.
186      */
MockContentProvider()187     protected MockContentProvider() {
188         super(new MockContext(), "", "", null);
189     }
190 
191     /**
192      * A constructor accepting a Context instance, which is supposed to be the subclasss of
193      * {@link MockContext}.
194      */
MockContentProvider(Context context)195     public MockContentProvider(Context context) {
196         super(context, "", "", null);
197     }
198 
199     /**
200      * A constructor which initialize four member variables which
201      * {@link android.content.ContentProvider} have internally.
202      *
203      * @param context A Context object which should be some mock instance (like the
204      * instance of {@link android.test.mock.MockContext}).
205      * @param readPermission The read permision you want this instance should have in the
206      * test, which is available via {@link #getReadPermission()}.
207      * @param writePermission The write permission you want this instance should have
208      * in the test, which is available via {@link #getWritePermission()}.
209      * @param pathPermissions The PathPermissions you want this instance should have
210      * in the test, which is available via {@link #getPathPermissions()}.
211      */
MockContentProvider(Context context, String readPermission, String writePermission, PathPermission[] pathPermissions)212     public MockContentProvider(Context context,
213             String readPermission,
214             String writePermission,
215             PathPermission[] pathPermissions) {
216         super(context, readPermission, writePermission, pathPermissions);
217     }
218 
219     @Override
delete(Uri uri, String selection, String[] selectionArgs)220     public int delete(Uri uri, String selection, String[] selectionArgs) {
221         throw new UnsupportedOperationException("unimplemented mock method");
222     }
223 
224     @Override
getType(Uri uri)225     public String getType(Uri uri) {
226         throw new UnsupportedOperationException("unimplemented mock method");
227     }
228 
229     /**
230      * @hide
231      */
232     @SuppressWarnings("deprecation")
getTypeAsync(Uri uri, RemoteCallback remoteCallback)233     public void getTypeAsync(Uri uri, RemoteCallback remoteCallback) {
234         AsyncTask.SERIAL_EXECUTOR.execute(() -> {
235             final Bundle bundle = new Bundle();
236             bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri));
237             remoteCallback.sendResult(bundle);
238         });
239     }
240 
241     @Override
insert(Uri uri, ContentValues values)242     public Uri insert(Uri uri, ContentValues values) {
243         throw new UnsupportedOperationException("unimplemented mock method");
244     }
245 
246     @Override
onCreate()247     public boolean onCreate() {
248         throw new UnsupportedOperationException("unimplemented mock method");
249     }
250 
251     @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)252     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
253             String sortOrder) {
254         throw new UnsupportedOperationException("unimplemented mock method");
255     }
256 
257     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)258     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
259         throw new UnsupportedOperationException("unimplemented mock method");
260     }
261 
262     /**
263      * If you're reluctant to implement this manually, please just call super.bulkInsert().
264      */
265     @Override
bulkInsert(Uri uri, ContentValues[] values)266     public int bulkInsert(Uri uri, ContentValues[] values) {
267         throw new UnsupportedOperationException("unimplemented mock method");
268     }
269 
270     @Override
attachInfo(Context context, ProviderInfo info)271     public void attachInfo(Context context, ProviderInfo info) {
272         throw new UnsupportedOperationException("unimplemented mock method");
273     }
274 
275     @Override
applyBatch(ArrayList<ContentProviderOperation> operations)276     public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
277         throw new UnsupportedOperationException("unimplemented mock method");
278     }
279 
280     /**
281      * @hide
282      */
283     @Override
call(String method, String request, Bundle args)284     public Bundle call(String method, String request, Bundle args) {
285         throw new UnsupportedOperationException("unimplemented mock method call");
286     }
287 
288     @Override
getStreamTypes(Uri url, String mimeTypeFilter)289     public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
290         throw new UnsupportedOperationException("unimplemented mock method call");
291     }
292 
293     @Override
openTypedAssetFile(Uri url, String mimeType, Bundle opts)294     public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts) {
295         throw new UnsupportedOperationException("unimplemented mock method call");
296     }
297 
298     /**
299      * @hide
300      */
301     @SuppressWarnings("deprecation")
canonicalizeAsync(Uri uri, RemoteCallback callback)302     public void canonicalizeAsync(Uri uri, RemoteCallback callback) {
303         AsyncTask.SERIAL_EXECUTOR.execute(() -> {
304             final Bundle bundle = new Bundle();
305             bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, canonicalize(uri));
306             callback.sendResult(bundle);
307         });
308     }
309 
310     /**
311      * @hide
312      */
refresh(Uri url, Bundle args)313     public boolean refresh(Uri url, Bundle args) {
314         throw new UnsupportedOperationException("unimplemented mock method call");
315     }
316 
317     /** {@hide} */
318     @Override
checkUriPermission(@onNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)319     public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
320         throw new UnsupportedOperationException("unimplemented mock method call");
321     }
322 
323     /**
324      * Returns IContentProvider which calls back same methods in this class.
325      * By overriding this class, we avoid the mechanism hidden behind ContentProvider
326      * (IPC, etc.)
327      *
328      * @hide
329      */
330     @Override
getIContentProvider()331     public final IContentProvider getIContentProvider() {
332         return mIContentProvider;
333     }
334 
335     /**
336      * @hide
337      */
getIContentProviderBinder()338     public IBinder getIContentProviderBinder() {
339         throw new UnsupportedOperationException("unimplemented mock method");
340     }
341 
342     /**
343      * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use
344      * when directly instantiating the provider for testing.
345      *
346      * <p>Provided for use by {@code android.test.ProviderTestCase2} and
347      * {@code android.test.RenamingDelegatingContext}.
348      *
349      * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
350      * New tests should be written using the
351      * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
352      */
353     @Deprecated
attachInfoForTesting( ContentProvider provider, Context context, ProviderInfo providerInfo)354     public static void attachInfoForTesting(
355             ContentProvider provider, Context context, ProviderInfo providerInfo) {
356         provider.attachInfoForTesting(context, providerInfo);
357     }
358 }
359