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