19c25925754f1660430822030455072ad1596f19bScott Su/*
29c25925754f1660430822030455072ad1596f19bScott Su * Copyright (C) 2008 The Android Open Source Project
39c25925754f1660430822030455072ad1596f19bScott Su *
49c25925754f1660430822030455072ad1596f19bScott Su * Licensed under the Apache License, Version 2.0 (the "License");
59c25925754f1660430822030455072ad1596f19bScott Su * you may not use this file except in compliance with the License.
69c25925754f1660430822030455072ad1596f19bScott Su * You may obtain a copy of the License at
79c25925754f1660430822030455072ad1596f19bScott Su *
89c25925754f1660430822030455072ad1596f19bScott Su *      http://www.apache.org/licenses/LICENSE-2.0
99c25925754f1660430822030455072ad1596f19bScott Su *
109c25925754f1660430822030455072ad1596f19bScott Su * Unless required by applicable law or agreed to in writing, software
119c25925754f1660430822030455072ad1596f19bScott Su * distributed under the License is distributed on an "AS IS" BASIS,
129c25925754f1660430822030455072ad1596f19bScott Su * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c25925754f1660430822030455072ad1596f19bScott Su * See the License for the specific language governing permissions and
149c25925754f1660430822030455072ad1596f19bScott Su * limitations under the License.
159c25925754f1660430822030455072ad1596f19bScott Su */
169c25925754f1660430822030455072ad1596f19bScott Su
179c25925754f1660430822030455072ad1596f19bScott Supackage android.content.cts;
189c25925754f1660430822030455072ad1596f19bScott Su
1959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport java.io.FileNotFoundException;
2059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport java.io.FileOutputStream;
2159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport java.io.IOException;
2259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport java.io.OutputStreamWriter;
2359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport java.io.PrintWriter;
2459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport java.io.UnsupportedEncodingException;
259c25925754f1660430822030455072ad1596f19bScott Suimport java.util.HashMap;
269c25925754f1660430822030455072ad1596f19bScott Su
279c25925754f1660430822030455072ad1596f19bScott Suimport android.content.ContentProvider;
289c25925754f1660430822030455072ad1596f19bScott Suimport android.content.ContentUris;
299c25925754f1660430822030455072ad1596f19bScott Suimport android.content.ContentValues;
309c25925754f1660430822030455072ad1596f19bScott Suimport android.content.Context;
319c25925754f1660430822030455072ad1596f19bScott Suimport android.content.UriMatcher;
3259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport android.content.ContentProvider.PipeDataWriter;
3359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport android.content.res.AssetFileDescriptor;
349c25925754f1660430822030455072ad1596f19bScott Suimport android.database.Cursor;
359c25925754f1660430822030455072ad1596f19bScott Suimport android.database.SQLException;
369c25925754f1660430822030455072ad1596f19bScott Suimport android.database.sqlite.SQLiteDatabase;
379c25925754f1660430822030455072ad1596f19bScott Suimport android.database.sqlite.SQLiteOpenHelper;
389c25925754f1660430822030455072ad1596f19bScott Suimport android.database.sqlite.SQLiteQueryBuilder;
399c25925754f1660430822030455072ad1596f19bScott Suimport android.net.Uri;
4059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport android.os.Bundle;
41362948e1020661076ec9ff6a11a8bdcc17f4dd2dJeff Brownimport android.os.CancellationSignal;
4259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport android.os.ParcelFileDescriptor;
439c25925754f1660430822030455072ad1596f19bScott Suimport android.text.TextUtils;
4459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornimport android.util.Log;
459c25925754f1660430822030455072ad1596f19bScott Su
4659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackbornpublic class MockContentProvider extends ContentProvider
4759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        implements PipeDataWriter<String> {
489c25925754f1660430822030455072ad1596f19bScott Su
499c25925754f1660430822030455072ad1596f19bScott Su    private SQLiteOpenHelper mOpenHelper;
509c25925754f1660430822030455072ad1596f19bScott Su
5159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private static final String DEFAULT_AUTHORITY = "ctstest";
5259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private static final String DEFAULT_DBNAME = "ctstest.db";
539c25925754f1660430822030455072ad1596f19bScott Su    private static final int DBVERSION = 2;
549c25925754f1660430822030455072ad1596f19bScott Su
559c25925754f1660430822030455072ad1596f19bScott Su    private static final int TESTTABLE1 = 1;
569c25925754f1660430822030455072ad1596f19bScott Su    private static final int TESTTABLE1_ID = 2;
5710ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown    private static final int TESTTABLE1_CROSS = 3;
5810ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown    private static final int TESTTABLE2 = 4;
5910ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown    private static final int TESTTABLE2_ID = 5;
6059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private static final int SELF_ID = 6;
6159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private static final int CRASH_ID = 6;
629c25925754f1660430822030455072ad1596f19bScott Su
6359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private final String mAuthority;
6459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private final String mDbName;
6559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private final UriMatcher URL_MATCHER;
6659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private HashMap<String, String> CTSDBTABLE1_LIST_PROJECTION_MAP;
6759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    private HashMap<String, String> CTSDBTABLE2_LIST_PROJECTION_MAP;
689c25925754f1660430822030455072ad1596f19bScott Su
699c25925754f1660430822030455072ad1596f19bScott Su    private static class DatabaseHelper extends SQLiteOpenHelper {
709c25925754f1660430822030455072ad1596f19bScott Su
7159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        DatabaseHelper(Context context, String dbname) {
7259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            super(context, dbname, null, DBVERSION);
739c25925754f1660430822030455072ad1596f19bScott Su        }
749c25925754f1660430822030455072ad1596f19bScott Su
759c25925754f1660430822030455072ad1596f19bScott Su        @Override
769c25925754f1660430822030455072ad1596f19bScott Su        public void onCreate(SQLiteDatabase db) {
779c25925754f1660430822030455072ad1596f19bScott Su            db.execSQL("CREATE TABLE TestTable1 ("
789c25925754f1660430822030455072ad1596f19bScott Su                    + "_id INTEGER PRIMARY KEY, " + "key TEXT, " + "value INTEGER"
799c25925754f1660430822030455072ad1596f19bScott Su                    + ");");
809c25925754f1660430822030455072ad1596f19bScott Su
819c25925754f1660430822030455072ad1596f19bScott Su            db.execSQL("CREATE TABLE TestTable2 ("
829c25925754f1660430822030455072ad1596f19bScott Su                    + "_id INTEGER PRIMARY KEY, " + "key TEXT, " + "value INTEGER"
839c25925754f1660430822030455072ad1596f19bScott Su                    + ");");
849c25925754f1660430822030455072ad1596f19bScott Su        }
859c25925754f1660430822030455072ad1596f19bScott Su
869c25925754f1660430822030455072ad1596f19bScott Su        @Override
879c25925754f1660430822030455072ad1596f19bScott Su        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
889c25925754f1660430822030455072ad1596f19bScott Su            db.execSQL("DROP TABLE IF EXISTS TestTable1");
899c25925754f1660430822030455072ad1596f19bScott Su            db.execSQL("DROP TABLE IF EXISTS TestTable2");
909c25925754f1660430822030455072ad1596f19bScott Su            onCreate(db);
919c25925754f1660430822030455072ad1596f19bScott Su        }
929c25925754f1660430822030455072ad1596f19bScott Su    }
939c25925754f1660430822030455072ad1596f19bScott Su
9459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    public MockContentProvider() {
9559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        this(DEFAULT_AUTHORITY, DEFAULT_DBNAME);
9659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    }
9759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
9859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    public MockContentProvider(String authority, String dbName) {
9959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        mAuthority = authority;
10059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        mDbName = dbName;
10159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
10259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
10359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "testtable1", TESTTABLE1);
10459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "testtable1/#", TESTTABLE1_ID);
10559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "testtable1/cross", TESTTABLE1_CROSS);
10659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "testtable2", TESTTABLE2);
10759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "testtable2/#", TESTTABLE2_ID);
10859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "self", SELF_ID);
10959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        URL_MATCHER.addURI(mAuthority, "crash", CRASH_ID);
11059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
11159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE1_LIST_PROJECTION_MAP = new HashMap<String, String>();
11259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE1_LIST_PROJECTION_MAP.put("_id", "_id");
11359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE1_LIST_PROJECTION_MAP.put("key", "key");
11459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE1_LIST_PROJECTION_MAP.put("value", "value");
11559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
11659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE2_LIST_PROJECTION_MAP = new HashMap<String, String>();
11759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE2_LIST_PROJECTION_MAP.put("_id", "_id");
11859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE2_LIST_PROJECTION_MAP.put("key", "key");
11959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        CTSDBTABLE2_LIST_PROJECTION_MAP.put("value", "value");
12059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    }
12159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
1229c25925754f1660430822030455072ad1596f19bScott Su    @Override
1239c25925754f1660430822030455072ad1596f19bScott Su    public boolean onCreate() {
12459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        mOpenHelper = new DatabaseHelper(getContext(), mDbName);
12559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        if (android.provider.Settings.System.getInt(getContext().getContentResolver(),
12659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                "__cts_crash_on_launch", 0) != 0) {
12759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            // The test case wants us to crash our process on first launch.
12859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            // Well, okay then!
12959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            Log.i("MockContentProvider", "TEST IS CRASHING SELF, CROSS FINGERS!");
13059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            android.provider.Settings.System.putInt(getContext().getContentResolver(),
13159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    "__cts_crash_on_launch", 0);
13259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            android.os.Process.killProcess(android.os.Process.myPid());
13359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        }
1349c25925754f1660430822030455072ad1596f19bScott Su        return true;
1359c25925754f1660430822030455072ad1596f19bScott Su    }
1369c25925754f1660430822030455072ad1596f19bScott Su
1379c25925754f1660430822030455072ad1596f19bScott Su    @Override
1389c25925754f1660430822030455072ad1596f19bScott Su    public int delete(Uri uri, String selection, String[] selectionArgs) {
1399c25925754f1660430822030455072ad1596f19bScott Su        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1409c25925754f1660430822030455072ad1596f19bScott Su        String segment;
1419c25925754f1660430822030455072ad1596f19bScott Su        int count;
1429c25925754f1660430822030455072ad1596f19bScott Su
1439c25925754f1660430822030455072ad1596f19bScott Su        switch (URL_MATCHER.match(uri)) {
1449c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1:
1459c25925754f1660430822030455072ad1596f19bScott Su            if (null == selection) {
1469c25925754f1660430822030455072ad1596f19bScott Su                // get the count when remove all rows
1479c25925754f1660430822030455072ad1596f19bScott Su                selection = "1";
1489c25925754f1660430822030455072ad1596f19bScott Su            }
1499c25925754f1660430822030455072ad1596f19bScott Su            count = db.delete("TestTable1", selection, selectionArgs);
1509c25925754f1660430822030455072ad1596f19bScott Su            break;
1519c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1_ID:
1529c25925754f1660430822030455072ad1596f19bScott Su            segment = uri.getPathSegments().get(1);
1539c25925754f1660430822030455072ad1596f19bScott Su            count = db.delete("TestTable1", "_id=" + segment +
1549c25925754f1660430822030455072ad1596f19bScott Su                    (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),
1559c25925754f1660430822030455072ad1596f19bScott Su                    selectionArgs);
1569c25925754f1660430822030455072ad1596f19bScott Su            break;
1579c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2:
1589c25925754f1660430822030455072ad1596f19bScott Su            count = db.delete("TestTable2", selection, selectionArgs);
1599c25925754f1660430822030455072ad1596f19bScott Su            break;
1609c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2_ID:
1619c25925754f1660430822030455072ad1596f19bScott Su            segment = uri.getPathSegments().get(1);
1629c25925754f1660430822030455072ad1596f19bScott Su            count = db.delete("TestTable2", "_id=" + segment +
1639c25925754f1660430822030455072ad1596f19bScott Su                    (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),
1649c25925754f1660430822030455072ad1596f19bScott Su                    selectionArgs);
1659c25925754f1660430822030455072ad1596f19bScott Su            break;
16659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        case SELF_ID:
16759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            // Wha...?  Delete ME?!?  O.K.!
16859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            Log.i("MockContentProvider", "Delete self requested!");
16959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            count = 1;
17059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            android.os.Process.killProcess(android.os.Process.myPid());
17159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            break;
1729c25925754f1660430822030455072ad1596f19bScott Su        default:
1739c25925754f1660430822030455072ad1596f19bScott Su            throw new IllegalArgumentException("Unknown URL " + uri);
1749c25925754f1660430822030455072ad1596f19bScott Su        }
1759c25925754f1660430822030455072ad1596f19bScott Su
1769c25925754f1660430822030455072ad1596f19bScott Su        getContext().getContentResolver().notifyChange(uri, null);
1779c25925754f1660430822030455072ad1596f19bScott Su        return count;
1789c25925754f1660430822030455072ad1596f19bScott Su    }
1799c25925754f1660430822030455072ad1596f19bScott Su
1809c25925754f1660430822030455072ad1596f19bScott Su    @Override
1819c25925754f1660430822030455072ad1596f19bScott Su    public String getType(Uri uri) {
1829c25925754f1660430822030455072ad1596f19bScott Su        switch (URL_MATCHER.match(uri)) {
1839c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1:
1849c25925754f1660430822030455072ad1596f19bScott Su            return "vnd.android.cursor.dir/com.android.content.testtable1";
1859c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1_ID:
1869c25925754f1660430822030455072ad1596f19bScott Su            return "vnd.android.cursor.item/com.android.content.testtable1";
18710ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown        case TESTTABLE1_CROSS:
18810ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown            return "vnd.android.cursor.cross/com.android.content.testtable1";
1899c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2:
1909c25925754f1660430822030455072ad1596f19bScott Su            return "vnd.android.cursor.dir/com.android.content.testtable2";
1919c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2_ID:
1929c25925754f1660430822030455072ad1596f19bScott Su            return "vnd.android.cursor.item/com.android.content.testtable2";
1939c25925754f1660430822030455072ad1596f19bScott Su
1949c25925754f1660430822030455072ad1596f19bScott Su        default:
1959c25925754f1660430822030455072ad1596f19bScott Su            throw new IllegalArgumentException("Unknown URL " + uri);
1969c25925754f1660430822030455072ad1596f19bScott Su        }
1979c25925754f1660430822030455072ad1596f19bScott Su    }
1989c25925754f1660430822030455072ad1596f19bScott Su
1999c25925754f1660430822030455072ad1596f19bScott Su    @Override
2009c25925754f1660430822030455072ad1596f19bScott Su    public Uri insert(Uri uri, ContentValues initialValues) {
2019c25925754f1660430822030455072ad1596f19bScott Su        long rowID;
2029c25925754f1660430822030455072ad1596f19bScott Su        ContentValues values;
2039c25925754f1660430822030455072ad1596f19bScott Su        String table;
2049c25925754f1660430822030455072ad1596f19bScott Su        Uri testUri;
2059c25925754f1660430822030455072ad1596f19bScott Su
2069c25925754f1660430822030455072ad1596f19bScott Su        if (initialValues != null)
2079c25925754f1660430822030455072ad1596f19bScott Su            values = new ContentValues(initialValues);
2089c25925754f1660430822030455072ad1596f19bScott Su        else
2099c25925754f1660430822030455072ad1596f19bScott Su            values = new ContentValues();
2109c25925754f1660430822030455072ad1596f19bScott Su
2119c25925754f1660430822030455072ad1596f19bScott Su        if (values.containsKey("value") == false)
2129c25925754f1660430822030455072ad1596f19bScott Su            values.put("value", -1);
2139c25925754f1660430822030455072ad1596f19bScott Su
2149c25925754f1660430822030455072ad1596f19bScott Su        switch (URL_MATCHER.match(uri)) {
2159c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1:
2169c25925754f1660430822030455072ad1596f19bScott Su            table = "TestTable1";
21759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            testUri = Uri.parse("content://" + mAuthority + "/testtable1");
2189c25925754f1660430822030455072ad1596f19bScott Su            break;
2199c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2:
2209c25925754f1660430822030455072ad1596f19bScott Su            table = "TestTable2";
22159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            testUri = Uri.parse("content://" + mAuthority + "/testtable2");
2229c25925754f1660430822030455072ad1596f19bScott Su            break;
2239c25925754f1660430822030455072ad1596f19bScott Su        default:
2249c25925754f1660430822030455072ad1596f19bScott Su            throw new IllegalArgumentException("Unknown URL " + uri);
2259c25925754f1660430822030455072ad1596f19bScott Su        }
2269c25925754f1660430822030455072ad1596f19bScott Su
2279c25925754f1660430822030455072ad1596f19bScott Su        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
2289c25925754f1660430822030455072ad1596f19bScott Su        rowID = db.insert(table, "key", values);
2299c25925754f1660430822030455072ad1596f19bScott Su
2309c25925754f1660430822030455072ad1596f19bScott Su        if (rowID > 0) {
2319c25925754f1660430822030455072ad1596f19bScott Su            Uri url = ContentUris.withAppendedId(testUri, rowID);
2329c25925754f1660430822030455072ad1596f19bScott Su            getContext().getContentResolver().notifyChange(url, null);
2339c25925754f1660430822030455072ad1596f19bScott Su            return url;
2349c25925754f1660430822030455072ad1596f19bScott Su        }
2359c25925754f1660430822030455072ad1596f19bScott Su
2369c25925754f1660430822030455072ad1596f19bScott Su        throw new SQLException("Failed to insert row into " + uri);
2379c25925754f1660430822030455072ad1596f19bScott Su    }
2389c25925754f1660430822030455072ad1596f19bScott Su
2399c25925754f1660430822030455072ad1596f19bScott Su    @Override
2409c25925754f1660430822030455072ad1596f19bScott Su    public Cursor query(Uri uri, String[] projection, String selection,
2419c25925754f1660430822030455072ad1596f19bScott Su            String[] selectionArgs, String sortOrder) {
24237ef3dff3135f88fc0894ebcf825f5d92482eac7Jeff Brown        return query(uri, projection, selection, selectionArgs, sortOrder, null);
24310ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown    }
24410ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown
24510ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown    @Override
24610ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown    public Cursor query(Uri uri, String[] projection, String selection,
247678cdd6accefbf443b04eb27ababde054a00ab02Jeff Brown            String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {
2489c25925754f1660430822030455072ad1596f19bScott Su
2499c25925754f1660430822030455072ad1596f19bScott Su        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
2509c25925754f1660430822030455072ad1596f19bScott Su
2519c25925754f1660430822030455072ad1596f19bScott Su        switch (URL_MATCHER.match(uri)) {
2529c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1:
2539c25925754f1660430822030455072ad1596f19bScott Su            qb.setTables("TestTable1");
2549c25925754f1660430822030455072ad1596f19bScott Su            qb.setProjectionMap(CTSDBTABLE1_LIST_PROJECTION_MAP);
2559c25925754f1660430822030455072ad1596f19bScott Su            break;
2569c25925754f1660430822030455072ad1596f19bScott Su
2579c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1_ID:
2589c25925754f1660430822030455072ad1596f19bScott Su            qb.setTables("TestTable1");
2599c25925754f1660430822030455072ad1596f19bScott Su            qb.appendWhere("_id=" + uri.getPathSegments().get(1));
2609c25925754f1660430822030455072ad1596f19bScott Su            break;
2619c25925754f1660430822030455072ad1596f19bScott Su
26210ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown        case TESTTABLE1_CROSS:
26310ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown            // Create a ridiculous cross-product of the test table.  This is done
26410ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown            // to create an artificially long-running query to enable us to test
265678cdd6accefbf443b04eb27ababde054a00ab02Jeff Brown            // remote query cancellation in ContentResolverTest.
26610ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown            qb.setTables("TestTable1 a, TestTable1 b, TestTable1 c, TestTable1 d, TestTable1 e");
26710ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown            break;
26810ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown
2699c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2:
2709c25925754f1660430822030455072ad1596f19bScott Su            qb.setTables("TestTable2");
2719c25925754f1660430822030455072ad1596f19bScott Su            qb.setProjectionMap(CTSDBTABLE2_LIST_PROJECTION_MAP);
2729c25925754f1660430822030455072ad1596f19bScott Su            break;
2739c25925754f1660430822030455072ad1596f19bScott Su
2749c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2_ID:
2759c25925754f1660430822030455072ad1596f19bScott Su            qb.setTables("TestTable2");
2769c25925754f1660430822030455072ad1596f19bScott Su            qb.appendWhere("_id=" + uri.getPathSegments().get(1));
2779c25925754f1660430822030455072ad1596f19bScott Su            break;
2789c25925754f1660430822030455072ad1596f19bScott Su
27959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        case CRASH_ID:
28059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            if (android.provider.Settings.System.getInt(getContext().getContentResolver(),
28159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    "__cts_crash_on_launch", 0) != 0) {
28259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                // The test case wants us to crash while querying.
28359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                // Well, okay then!
28459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                Log.i("MockContentProvider", "TEST IS CRASHING SELF, CROSS FINGERS!");
28559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                android.provider.Settings.System.putInt(getContext().getContentResolver(),
28659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        "__cts_crash_on_launch", 0);
28759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                android.os.Process.killProcess(android.os.Process.myPid());
28859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            }
28959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            qb.setTables("TestTable1");
29059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            qb.setProjectionMap(CTSDBTABLE1_LIST_PROJECTION_MAP);
29159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            break;
29259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
2939c25925754f1660430822030455072ad1596f19bScott Su        default:
2949c25925754f1660430822030455072ad1596f19bScott Su            throw new IllegalArgumentException("Unknown URL " + uri);
2959c25925754f1660430822030455072ad1596f19bScott Su        }
2969c25925754f1660430822030455072ad1596f19bScott Su
2979c25925754f1660430822030455072ad1596f19bScott Su        /* If no sort order is specified use the default */
2989c25925754f1660430822030455072ad1596f19bScott Su        String orderBy;
2999c25925754f1660430822030455072ad1596f19bScott Su        if (TextUtils.isEmpty(sortOrder))
3009c25925754f1660430822030455072ad1596f19bScott Su            orderBy = "_id";
3019c25925754f1660430822030455072ad1596f19bScott Su        else
3029c25925754f1660430822030455072ad1596f19bScott Su            orderBy = sortOrder;
3039c25925754f1660430822030455072ad1596f19bScott Su
3049c25925754f1660430822030455072ad1596f19bScott Su        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
30510ed07310a567e85a6fbc240bbf001ccac3d5a7eJeff Brown        Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy,
306678cdd6accefbf443b04eb27ababde054a00ab02Jeff Brown                null, cancellationSignal);
3079c25925754f1660430822030455072ad1596f19bScott Su
3089c25925754f1660430822030455072ad1596f19bScott Su        c.setNotificationUri(getContext().getContentResolver(), uri);
3099c25925754f1660430822030455072ad1596f19bScott Su        return c;
3109c25925754f1660430822030455072ad1596f19bScott Su    }
3119c25925754f1660430822030455072ad1596f19bScott Su
3129c25925754f1660430822030455072ad1596f19bScott Su    @Override
3139c25925754f1660430822030455072ad1596f19bScott Su    public int update(Uri uri, ContentValues values, String selection,
3149c25925754f1660430822030455072ad1596f19bScott Su            String[] selectionArgs) {
3159c25925754f1660430822030455072ad1596f19bScott Su        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
3169c25925754f1660430822030455072ad1596f19bScott Su        String segment;
3179c25925754f1660430822030455072ad1596f19bScott Su        int count;
3189c25925754f1660430822030455072ad1596f19bScott Su
3199c25925754f1660430822030455072ad1596f19bScott Su        switch (URL_MATCHER.match(uri)) {
3209c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1:
3219c25925754f1660430822030455072ad1596f19bScott Su            count = db.update("TestTable1", values, selection, selectionArgs);
3229c25925754f1660430822030455072ad1596f19bScott Su            break;
3239c25925754f1660430822030455072ad1596f19bScott Su
3249c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE1_ID:
3259c25925754f1660430822030455072ad1596f19bScott Su            segment = uri.getPathSegments().get(1);
3269c25925754f1660430822030455072ad1596f19bScott Su            count = db.update("TestTable1", values, "_id=" + segment +
3279c25925754f1660430822030455072ad1596f19bScott Su                    (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),
3289c25925754f1660430822030455072ad1596f19bScott Su                    selectionArgs);
3299c25925754f1660430822030455072ad1596f19bScott Su            break;
3309c25925754f1660430822030455072ad1596f19bScott Su
3319c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2:
3329c25925754f1660430822030455072ad1596f19bScott Su            count = db.update("TestTable2", values, selection, selectionArgs);
3339c25925754f1660430822030455072ad1596f19bScott Su            break;
3349c25925754f1660430822030455072ad1596f19bScott Su
3359c25925754f1660430822030455072ad1596f19bScott Su        case TESTTABLE2_ID:
3369c25925754f1660430822030455072ad1596f19bScott Su            segment = uri.getPathSegments().get(1);
3379c25925754f1660430822030455072ad1596f19bScott Su            count = db.update("TestTable2", values, "_id=" + segment +
3389c25925754f1660430822030455072ad1596f19bScott Su                    (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),
3399c25925754f1660430822030455072ad1596f19bScott Su                    selectionArgs);
3409c25925754f1660430822030455072ad1596f19bScott Su            break;
3419c25925754f1660430822030455072ad1596f19bScott Su
3429c25925754f1660430822030455072ad1596f19bScott Su        default:
3439c25925754f1660430822030455072ad1596f19bScott Su            throw new IllegalArgumentException("Unknown URL " + uri);
3449c25925754f1660430822030455072ad1596f19bScott Su        }
3459c25925754f1660430822030455072ad1596f19bScott Su
3469c25925754f1660430822030455072ad1596f19bScott Su        getContext().getContentResolver().notifyChange(uri, null);
3479c25925754f1660430822030455072ad1596f19bScott Su        return count;
3489c25925754f1660430822030455072ad1596f19bScott Su    }
3499c25925754f1660430822030455072ad1596f19bScott Su
35059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    @Override
35159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
35259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        switch (URL_MATCHER.match(uri)) {
35359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            case CRASH_ID:
35459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                if (android.provider.Settings.System.getInt(getContext().getContentResolver(),
35559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        "__cts_crash_on_launch", 0) != 0) {
35659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    // The test case wants us to crash while querying.
35759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    // Well, okay then!
35859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    Log.i("MockContentProvider", "TEST IS CRASHING SELF, CROSS FINGERS!");
35959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    android.provider.Settings.System.putInt(getContext().getContentResolver(),
36059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                            "__cts_crash_on_launch", 0);
36159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    android.os.Process.killProcess(android.os.Process.myPid());
36259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                }
36359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                return new AssetFileDescriptor(
36459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        openPipeHelper(uri, null, null,
36559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                                "This is the openAssetFile test data!", this), 0,
36659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        AssetFileDescriptor.UNKNOWN_LENGTH);
36759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
36859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            default:
36959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                return super.openAssetFile(uri, mode);
37059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        }
37159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    }
3729c25925754f1660430822030455072ad1596f19bScott Su
37359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    @Override
37459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
37559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            throws FileNotFoundException {
37659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        switch (URL_MATCHER.match(uri)) {
37759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            case CRASH_ID:
37859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                if (android.provider.Settings.System.getInt(getContext().getContentResolver(),
37959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        "__cts_crash_on_launch", 0) != 0) {
38059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    // The test case wants us to crash while querying.
38159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    // Well, okay then!
38259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    Log.i("MockContentProvider", "TEST IS CRASHING SELF, CROSS FINGERS!");
38359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    android.provider.Settings.System.putInt(getContext().getContentResolver(),
38459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                            "__cts_crash_on_launch", 0);
38559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                    android.os.Process.killProcess(android.os.Process.myPid());
38659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                }
38759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                return new AssetFileDescriptor(
38859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        openPipeHelper(uri, null, null,
38959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                                "This is the openTypedAssetFile test data!", this), 0,
39059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                        AssetFileDescriptor.UNKNOWN_LENGTH);
39159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn
39259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            default:
39359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                return super.openTypedAssetFile(uri, mimeTypeFilter, opts);
39459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        }
39559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    }
3969c25925754f1660430822030455072ad1596f19bScott Su
39759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    @Override
39859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn    public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, Bundle opts,
39959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            String args) {
40059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        FileOutputStream fout = new FileOutputStream(output.getFileDescriptor());
40159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        PrintWriter pw = null;
40259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        try {
40359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            pw = new PrintWriter(new OutputStreamWriter(fout, "UTF-8"));
40459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            pw.print(args);
40559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        } catch (UnsupportedEncodingException e) {
40659069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            Log.w("MockContentProvider", "Ooops", e);
40759069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        } finally {
40859069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            if (pw != null) {
40959069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                pw.flush();
41059069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            }
41159069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            try {
41259069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn                fout.close();
41359069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            } catch (IOException e) {
41459069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn            }
41559069a7ff3f9f1fe7b3fb2072802778ac3c10098Dianne Hackborn        }
4169c25925754f1660430822030455072ad1596f19bScott Su    }
4179c25925754f1660430822030455072ad1596f19bScott Su}
418