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