1 /*
2  * Copyright (C) 2017 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.content.cts;
18 
19 import android.content.ContentProvider;
20 import android.content.ContentResolver;
21 import android.content.ContentValues;
22 import android.database.Cursor;
23 import android.database.MatrixCursor;
24 import android.database.MatrixCursor.RowBuilder;
25 import android.net.Uri;
26 import android.os.Bundle;
27 import android.os.CancellationSignal;
28 import android.util.Log;
29 
30 import javax.annotation.Nullable;
31 
32 /**
33  * A stub data paging provider used for testing of paging support.
34  * Ignores client supplied projections.
35  */
36 public final class TestPagingContentProvider extends ContentProvider {
37 
38     static final String AUTHORITY = "android.content.cts.testpagingprovider";
39 
40     static final Uri PAGED_DATA_URI = Uri.parse("content://" + AUTHORITY + "/paged/");
41     static final Uri UNPAGED_DATA_URI = Uri.parse("content://" + AUTHORITY + "/un-paged/");
42 
43     /** Required queryArgument specifying corpus size. */
44     static final String RECORD_COUNT = "test-record-count";
45     static final String COLUMN_POS = "ColumnPos";
46     static final String COLUMN_A = "ColumnA";
47     static final String COLUMN_B = "ColumnB";
48     static final String COLUMN_C = "ColumnC";
49     static final String COLUMN_D = "ColumnD";
50     static final String[] PROJECTION = {
51         COLUMN_POS,
52         COLUMN_A,
53         COLUMN_B,
54         COLUMN_C,
55         COLUMN_D
56     };
57 
58     private static final String TAG = "TestPagingContentProvider";
59 
60     @Override
onCreate()61     public boolean onCreate() {
62         return true;
63     }
64 
65     @Override
query(Uri uri, String[] ignored, Bundle queryArgs, CancellationSignal cancellationSignal)66     public Cursor query(Uri uri, String[] ignored, Bundle queryArgs,
67             CancellationSignal cancellationSignal) {
68 
69         queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
70 
71         int recordCount = queryArgs.getInt(RECORD_COUNT, Integer.MIN_VALUE);
72         if (recordCount == Integer.MIN_VALUE) {
73             throw new RuntimeException("Recordset size must be specified.");
74         }
75 
76         if (recordCount < 0) {
77             throw new RuntimeException("Recordset size must be >= 0");
78         }
79 
80         Cursor cursor = null;
81         if (PAGED_DATA_URI.equals(uri)) {
82             cursor = buildPagedResults(queryArgs, recordCount);
83         } else if (UNPAGED_DATA_URI.equals(uri)) {
84             cursor = buildUnpagedResults(recordCount);
85         }
86 
87         if (cursor == null) {
88             throw new IllegalArgumentException("Unsupported URI: " + uri);
89         }
90 
91         cursor.setNotificationUri(getContext().getContentResolver(), uri);
92 
93         Log.v(TAG, "Final cursor contains " + cursor.getCount() + " rows.");
94         return cursor;
95     }
96 
buildPagedResults(Bundle queryArgs, int recordsetSize)97     private Cursor buildPagedResults(Bundle queryArgs, int recordsetSize) {
98 
99         int offset = queryArgs.getInt(ContentResolver.QUERY_ARG_OFFSET, 0);
100         int limit = queryArgs.getInt(ContentResolver.QUERY_ARG_LIMIT, Integer.MIN_VALUE);
101 
102         Log.v(TAG, "Building paged results. {"
103                 + "recordsetSize=" + recordsetSize
104                 + ", offset=" + offset
105                 + ", limit=" + limit + "}");
106 
107         MatrixCursor c = createCursor();
108         Bundle extras = c.getExtras();
109 
110         // Calculate the number of items to include in the cursor.
111         int numItems = recordsetSize - offset;
112         numItems = numItems < 0 ? 0 : (numItems > limit ? limit : numItems);
113 
114         // Build the paged result set.
115         for (int i = offset; i < offset + numItems; i++) {
116             fillRow(c.newRow(), i);
117         }
118 
119         extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, new String[] {
120             ContentResolver.QUERY_ARG_OFFSET,
121             ContentResolver.QUERY_ARG_LIMIT
122         });
123         extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize);
124         return c;
125     }
126 
buildUnpagedResults(int recordsetSize)127     private Cursor buildUnpagedResults(int recordsetSize) {
128 
129         Log.v(TAG, "Building un-paged results. {" + "recordsetSize=" + recordsetSize + "}");
130 
131         MatrixCursor c = createCursor();
132 
133         // Build the unpaged result set.
134         for (int i = 0; i < recordsetSize; i++) {
135             fillRow(c.newRow(), i);
136         }
137 
138         return c;
139     }
140 
createCursor()141     private MatrixCursor createCursor() {
142         MatrixCursor c = new MatrixCursor(PROJECTION);
143         Bundle extras = new Bundle();
144         c.setExtras(extras);
145         return c;
146     }
147 
fillRow(RowBuilder row, int pos)148     private void fillRow(RowBuilder row, int pos) {
149         row.add(COLUMN_POS, pos);
150         row.add(COLUMN_A, "--aaa--" + pos);
151         row.add(COLUMN_B, "**bbb**" + pos);
152         row.add(COLUMN_C, "^^ccc^^" + pos);
153         row.add(COLUMN_D, "##ddd##" + pos);
154     }
155 
156     @Override
query( Uri uri, @Nullable String[] projection, String selection, String[] selectionArgs, String sortOrder)157     public Cursor query(
158             Uri uri, @Nullable String[] projection, String selection, String[] selectionArgs,
159             String sortOrder) {
160         throw new UnsupportedOperationException("Call query w/ Bundle args");
161     }
162 
163     @Override
getType(Uri uri)164     public String getType(Uri uri) {
165         throw new UnsupportedOperationException();
166     }
167 
168     @Override
insert(Uri uri, ContentValues values)169     public Uri insert(Uri uri, ContentValues values) {
170         throw new UnsupportedOperationException();
171     }
172 
173     @Override
delete(Uri uri, String selection, String[] selectionArgs)174     public int delete(Uri uri, String selection, String[] selectionArgs) {
175         throw new UnsupportedOperationException();
176     }
177 
178     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)179     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
180         throw new UnsupportedOperationException();
181     }
182 }
183