1 /*
2  * Copyright (C) 2010 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.cts.verifier;
18 
19 import com.android.compatibility.common.util.ReportLog;
20 
21 import android.app.backup.BackupManager;
22 import android.content.ContentProvider;
23 import android.content.ContentResolver;
24 import android.content.ContentValues;
25 import android.content.Context;
26 import android.content.UriMatcher;
27 import android.database.Cursor;
28 import android.database.sqlite.SQLiteDatabase;
29 import android.database.sqlite.SQLiteOpenHelper;
30 import android.database.sqlite.SQLiteQueryBuilder;
31 import android.net.Uri;
32 
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35 import java.io.ObjectOutputStream;
36 
37 /** {@link ContentProvider} that provides read and write access to the test results. */
38 public class TestResultsProvider extends ContentProvider {
39 
40     private static final String RESULTS_PATH = "results";
41 
42     /**
43      * Get the URI from the result content.
44      * @param context
45      * @return Uri
46      */
getResultContentUri(Context context)47     public static Uri getResultContentUri(Context context) {
48         final String packageName = context.getPackageName();
49         final Uri contentUri = Uri.parse("content://" + packageName + ".testresultsprovider");
50         return Uri.withAppendedPath(contentUri, RESULTS_PATH);
51     }
52 
53     /**
54      * Get the URI from the test name.
55      * @param context
56      * @param testName
57      * @return Uri
58      */
getTestNameUri(Context context)59     public static Uri getTestNameUri(Context context) {
60         final String testName = context.getClass().getName();
61         return Uri.withAppendedPath(getResultContentUri(context), testName);
62     }
63 
64     static final String _ID = "_id";
65 
66     /** String name of the test like "com.android.cts.verifier.foo.FooTestActivity" */
67     static final String COLUMN_TEST_NAME = "testname";
68 
69     /** Integer test result corresponding to constants in {@link TestResult}. */
70     static final String COLUMN_TEST_RESULT = "testresult";
71 
72     /** Boolean indicating whether the test info has been seen. */
73     static final String COLUMN_TEST_INFO_SEEN = "testinfoseen";
74 
75     /** String containing the test's details. */
76     static final String COLUMN_TEST_DETAILS = "testdetails";
77 
78     /** ReportLog containing the test result metrics. */
79     static final String COLUMN_TEST_METRICS = "testmetrics";
80 
81     private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
82     private static final int RESULTS_ALL = 1;
83     private static final int RESULTS_ID = 2;
84     private static final int RESULTS_TEST_NAME = 3;
85 
86     private static final String TABLE_NAME = "results";
87 
88     private SQLiteOpenHelper mOpenHelper;
89 
90     private BackupManager mBackupManager;
91 
92     @Override
onCreate()93     public boolean onCreate() {
94         final String authority = getContext().getPackageName() + ".testresultsprovider";
95 
96         URI_MATCHER.addURI(authority, RESULTS_PATH, RESULTS_ALL);
97         URI_MATCHER.addURI(authority, RESULTS_PATH + "/#", RESULTS_ID);
98         URI_MATCHER.addURI(authority, RESULTS_PATH + "/*", RESULTS_TEST_NAME);
99 
100         mOpenHelper = new TestResultsOpenHelper(getContext());
101         mBackupManager = new BackupManager(getContext());
102         return false;
103     }
104 
105     private static class TestResultsOpenHelper extends SQLiteOpenHelper {
106 
107         private static final String DATABASE_NAME = "results.db";
108 
109         private static final int DATABASE_VERSION = 6;
110 
TestResultsOpenHelper(Context context)111         TestResultsOpenHelper(Context context) {
112             super(context, DATABASE_NAME, null, DATABASE_VERSION);
113         }
114 
115         @Override
onCreate(SQLiteDatabase db)116         public void onCreate(SQLiteDatabase db) {
117             db.execSQL("CREATE TABLE " + TABLE_NAME + " ("
118                     + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
119                     + COLUMN_TEST_NAME + " TEXT, "
120                     + COLUMN_TEST_RESULT + " INTEGER,"
121                     + COLUMN_TEST_INFO_SEEN + " INTEGER DEFAULT 0,"
122                     + COLUMN_TEST_DETAILS + " TEXT,"
123                     + COLUMN_TEST_METRICS + " BLOB);");
124         }
125 
126         @Override
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)127         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
128             db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
129             onCreate(db);
130         }
131     }
132 
133     @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)134     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
135             String sortOrder) {
136         SQLiteQueryBuilder query = new SQLiteQueryBuilder();
137         query.setTables(TABLE_NAME);
138 
139         int match = URI_MATCHER.match(uri);
140         switch (match) {
141             case RESULTS_ALL:
142                 break;
143 
144             case RESULTS_ID:
145                 query.appendWhere(_ID);
146                 query.appendWhere("=");
147                 query.appendWhere(uri.getPathSegments().get(1));
148                 break;
149 
150             case RESULTS_TEST_NAME:
151                 query.appendWhere(COLUMN_TEST_NAME);
152                 query.appendWhere("=");
153                 query.appendWhere("\"" + uri.getPathSegments().get(1) + "\"");
154                 break;
155 
156             default:
157                 throw new IllegalArgumentException("Unknown URI: " + uri);
158         }
159 
160         SQLiteDatabase db = mOpenHelper.getReadableDatabase();
161         return query.query(db, projection, selection, selectionArgs, null, null, sortOrder);
162     }
163 
164     @Override
insert(Uri uri, ContentValues values)165     public Uri insert(Uri uri, ContentValues values) {
166         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
167         long id = db.insert(TABLE_NAME, null, values);
168         getContext().getContentResolver().notifyChange(uri, null);
169         mBackupManager.dataChanged();
170         return Uri.withAppendedPath(getResultContentUri(getContext()), "" + id);
171     }
172 
173     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)174     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
175         int match = URI_MATCHER.match(uri);
176         switch (match) {
177             case RESULTS_ALL:
178                 break;
179 
180             case RESULTS_ID:
181                 String idSelection = _ID + "=" + uri.getPathSegments().get(1);
182                 if (selection != null && selection.length() > 0) {
183                     selection = idSelection + " AND " + selection;
184                 } else {
185                     selection = idSelection;
186                 }
187                 break;
188 
189             case RESULTS_TEST_NAME:
190                 String testNameSelection = COLUMN_TEST_NAME + "=\""
191                         + uri.getPathSegments().get(1) + "\"";
192                 if (selection != null && selection.length() > 0) {
193                     selection = testNameSelection + " AND " + selection;
194                 } else {
195                     selection = testNameSelection;
196                 }
197                 break;
198 
199             default:
200                 throw new IllegalArgumentException("Unknown URI: " + uri);
201         }
202 
203         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
204         int numUpdated = db.update(TABLE_NAME, values, selection, selectionArgs);
205         if (numUpdated > 0) {
206             getContext().getContentResolver().notifyChange(uri, null);
207             mBackupManager.dataChanged();
208         }
209         return numUpdated;
210     }
211 
212     @Override
delete(Uri uri, String selection, String[] selectionArgs)213     public int delete(Uri uri, String selection, String[] selectionArgs) {
214         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
215         int numDeleted = db.delete(TABLE_NAME, selection, selectionArgs);
216         if (numDeleted > 0) {
217             getContext().getContentResolver().notifyChange(uri, null);
218             mBackupManager.dataChanged();
219         }
220         return numDeleted;
221     }
222 
223     @Override
getType(Uri uri)224     public String getType(Uri uri) {
225         return null;
226     }
227 
setTestResult(Context context, String testName, int testResult, String testDetails, ReportLog reportLog)228     static void setTestResult(Context context, String testName, int testResult,
229             String testDetails, ReportLog reportLog) {
230         ContentValues values = new ContentValues(2);
231         values.put(TestResultsProvider.COLUMN_TEST_RESULT, testResult);
232         values.put(TestResultsProvider.COLUMN_TEST_NAME, testName);
233         values.put(TestResultsProvider.COLUMN_TEST_DETAILS, testDetails);
234         values.put(TestResultsProvider.COLUMN_TEST_METRICS, serialize(reportLog));
235 
236         final Uri uri = getResultContentUri(context);
237         ContentResolver resolver = context.getContentResolver();
238         int numUpdated = resolver.update(uri, values,
239                 TestResultsProvider.COLUMN_TEST_NAME + " = ?",
240                 new String[] {testName});
241 
242         if (numUpdated == 0) {
243             resolver.insert(uri, values);
244         }
245     }
246 
serialize(Object o)247     private static byte[] serialize(Object o) {
248         ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
249         ObjectOutputStream objectOutput = null;
250         try {
251             objectOutput = new ObjectOutputStream(byteStream);
252             objectOutput.writeObject(o);
253             return byteStream.toByteArray();
254         } catch (IOException e) {
255             return null;
256         } finally {
257             try {
258                 if (objectOutput != null) {
259                     objectOutput.close();
260                 }
261                 byteStream.close();
262             } catch (IOException e) {
263                 // Ignore close exception.
264             }
265         }
266     }
267 }
268