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