1 /* 2 * Copyright (C) 2015 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 com.android.messaging; 18 19 import android.content.ContentProvider; 20 import android.content.ContentProviderClient; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.content.pm.ProviderInfo; 24 import android.database.Cursor; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.os.RemoteException; 28 import androidx.collection.SimpleArrayMap; 29 import android.text.TextUtils; 30 31 import com.android.messaging.datamodel.FakeCursor; 32 import com.android.messaging.util.LogUtil; 33 34 import java.util.ArrayList; 35 36 public class FakeContentProvider extends ContentProvider { 37 38 private static class ContentOverride { 39 private final String uri; 40 private final String where; 41 private final String args; 42 private final String[] columns; 43 private final Object[][] data; 44 ContentOverride(final String uri, final String where, final String args, final String[] columns, final Object[][] data)45 ContentOverride(final String uri, final String where, final String args, 46 final String[] columns, final Object[][] data) { 47 this.uri = uri; 48 this.where = where; 49 this.args = args; 50 this.columns = columns; 51 this.data = data; 52 } 53 match(final String uri, final String where, final String[] args)54 boolean match(final String uri, final String where, final String[] args) { 55 if (!this.uri.equals(uri) || !TextUtils.equals(this.where, where)) { 56 return false; 57 } 58 59 if (this.args == null || args == null) { 60 return this.args == null && args == null; 61 } 62 63 return this.args.equals(TextUtils.join(";", args)); 64 } 65 } 66 67 private final Context mGlobalContext; 68 private final ArrayList<ContentOverride> mOverrides = new ArrayList<ContentOverride>(); 69 private final SimpleArrayMap<String, String> mTypes = new SimpleArrayMap<String, String>(); 70 private final ContentProviderClient mProvider; 71 private final Uri mUri; 72 FakeContentProvider(final Context context, final Uri uri, final boolean canDelegate)73 public FakeContentProvider(final Context context, final Uri uri, final boolean canDelegate) { 74 mGlobalContext = context; 75 mUri = uri; 76 if (canDelegate) { 77 mProvider = mGlobalContext.getContentResolver().acquireContentProviderClient(mUri); 78 } else { 79 mProvider = null; 80 } 81 82 ProviderInfo providerInfo = new ProviderInfo(); 83 providerInfo.authority = uri.getAuthority(); 84 85 this.attachInfo(mGlobalContext, providerInfo); 86 } 87 addOverrideData(final Uri uri, final String where, final String args, final String[] columns, final Object[][] data)88 public void addOverrideData(final Uri uri, final String where, final String args, 89 final String[] columns, final Object[][] data) { 90 mOverrides.add(new ContentOverride(uri.toString(), where, args, columns, data)); 91 } 92 addOverrideType(final Uri uri, final String type)93 public void addOverrideType(final Uri uri, final String type) { 94 mTypes.put(uri.toString(), type); 95 } 96 97 @Override onCreate()98 public boolean onCreate() { 99 return false; 100 } 101 102 @Override shutdown()103 public void shutdown() { 104 if (mProvider != null) { 105 mProvider.release(); 106 } 107 } 108 109 @Override query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder)110 public Cursor query(final Uri uri, final String[] projection, final String selection, 111 final String[] selectionArgs, final String sortOrder) { 112 LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: query " + uri.toString() 113 + " for " + (projection == null ? null : TextUtils.join(",", projection)) 114 + " where " + selection 115 + " with " + (selectionArgs == null ? null : TextUtils.join(";", selectionArgs))); 116 117 for(final ContentOverride content : mOverrides) { 118 if (content.match(uri.toString(), selection, selectionArgs)) { 119 return new FakeCursor(projection, content.columns, content.data); 120 } 121 } 122 if (mProvider != null) { 123 try { 124 LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: delgating"); 125 126 final Cursor cursor = mProvider.query(uri, projection, selection, selectionArgs, 127 sortOrder); 128 129 LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: response size " 130 + cursor.getCount() + " contains " + TextUtils.join(",", 131 cursor.getColumnNames()) + " type(0) " + cursor.getType(0)); 132 133 return cursor; 134 } catch (final RemoteException e) { 135 e.printStackTrace(); 136 } 137 } 138 return null; 139 } 140 141 @Override getType(final Uri uri)142 public String getType(final Uri uri) { 143 String type = mTypes.get(uri.toString()); 144 if (type == null) { 145 try { 146 type = mProvider.getType(uri); 147 } catch (final RemoteException e) { 148 e.printStackTrace(); 149 } 150 } 151 return type; 152 } 153 154 @Override insert(final Uri uri, final ContentValues values)155 public Uri insert(final Uri uri, final ContentValues values) { 156 // TODO: Add code to track insert operations and return correct status 157 throw new UnsupportedOperationException(); 158 } 159 160 @Override delete(final Uri uri, final String selection, final String[] selectionArgs)161 public int delete(final Uri uri, final String selection, final String[] selectionArgs) { 162 // TODO: Add code to track delete operations and return correct status 163 throw new UnsupportedOperationException(); 164 } 165 166 @Override update(final Uri uri, final ContentValues values, final String selection, final String[] selectionArgs)167 public int update(final Uri uri, final ContentValues values, final String selection, 168 final String[] selectionArgs) { 169 // TODO: Add code to track update operations and return correct status 170 throw new UnsupportedOperationException(); 171 } 172 call(final String callingPkg, final String method, final String arg, final Bundle extras)173 public Bundle call(final String callingPkg, final String method, final String arg, 174 final Bundle extras) { 175 return null; 176 } 177 } 178