Home | History | Annotate | Download | only in testing
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      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 
     15 package android.testing;
     16 
     17 import android.content.ContentProvider;
     18 import android.content.ContentResolver;
     19 import android.content.Context;
     20 import android.content.IContentProvider;
     21 import android.database.ContentObserver;
     22 import android.net.Uri;
     23 import android.util.ArraySet;
     24 
     25 import com.google.android.collect.Maps;
     26 
     27 import java.util.Map;
     28 
     29 /**
     30  * 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)
     35  */
     36 public class TestableContentResolver extends ContentResolver {
     37 
     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 
     43     public TestableContentResolver(Context context) {
     44         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 }
    136