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 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 { 73 URI_MATCHER.addURI(AUTHORITY, RESULTS_PATH, RESULTS_ALL); 74 URI_MATCHER.addURI(AUTHORITY, RESULTS_PATH + "/#", RESULTS_ID); 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 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 97 TestResultsOpenHelper(Context context) { 98 super(context, DATABASE_NAME, null, DATABASE_VERSION); 99 } 100 101 @Override 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 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 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 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 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 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 210 public String getType(Uri uri) { 211 return null; 212 } 213 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 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