diff options
4 files changed, 263 insertions, 210 deletions
diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java index 31f0e3145f8a..05e97c7ef1e9 100644 --- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java +++ b/services/core/java/com/android/server/timezone/PackageStatusStorage.java @@ -16,73 +16,83 @@ package com.android.server.timezone; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; +import com.android.internal.util.FastXmlSerializer; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import android.util.AtomicFile; import android.util.Slog; +import android.util.Xml; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_FAILURE; import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_SUCCESS; import static com.android.server.timezone.PackageStatus.CHECK_STARTED; +import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; +import static org.xmlpull.v1.XmlPullParser.START_TAG; /** * Storage logic for accessing/mutating the Android system's persistent state related to time zone - * update checking. There is expected to be a single instance and all methods synchronized on - * {@code this} for thread safety. + * update checking. There is expected to be a single instance. All non-private methods are thread + * safe. */ final class PackageStatusStorage { - private static final String TAG = "timezone.PackageStatusStorage"; + private static final String LOG_TAG = "timezone.PackageStatusStorage"; - private static final String DATABASE_NAME = "timezonepackagestatus.db"; - private static final int DATABASE_VERSION = 1; - - /** The table name. It will have a single row with _id == {@link #SINGLETON_ID} */ - private static final String TABLE = "status"; - private static final String COLUMN_ID = "_id"; + private static final String TAG_PACKAGE_STATUS = "PackageStatus"; /** - * Column that stores a monotonically increasing lock ID, used to detect concurrent update + * Attribute that stores a monotonically increasing lock ID, used to detect concurrent update * issues without on-line locks. Incremented on every write. */ - private static final String COLUMN_OPTIMISTIC_LOCK_ID = "optimistic_lock_id"; + private static final String ATTRIBUTE_OPTIMISTIC_LOCK_ID = "optimisticLockId"; /** - * Column that stores the current "check status" of the time zone update application packages. + * Attribute that stores the current "check status" of the time zone update application + * packages. */ - private static final String COLUMN_CHECK_STATUS = "check_status"; + private static final String ATTRIBUTE_CHECK_STATUS = "checkStatus"; /** - * Column that stores the version of the time zone rules update application being checked / last - * checked. + * Attribute that stores the version of the time zone rules update application being checked + * / last checked. */ - private static final String COLUMN_UPDATE_APP_VERSION = "update_app_package_version"; + private static final String ATTRIBUTE_UPDATE_APP_VERSION = "updateAppPackageVersion"; /** - * Column that stores the version of the time zone rules data application being checked / last - * checked. + * Attribute that stores the version of the time zone rules data application being checked + * / last checked. */ - private static final String COLUMN_DATA_APP_VERSION = "data_app_package_version"; - - /** - * The ID of the one row. - */ - private static final int SINGLETON_ID = 1; + private static final String ATTRIBUTE_DATA_APP_VERSION = "dataAppPackageVersion"; private static final int UNKNOWN_PACKAGE_VERSION = -1; - private final DatabaseHelper mDatabaseHelper; + private final AtomicFile mPackageStatusFile; - PackageStatusStorage(Context context) { - mDatabaseHelper = new DatabaseHelper(context); + PackageStatusStorage(File storageDir) { + mPackageStatusFile = new AtomicFile(new File(storageDir, "packageStatus.xml")); + if (!mPackageStatusFile.getBaseFile().exists()) { + try { + insertInitialPackageStatus(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } } - void deleteDatabaseForTests() { - SQLiteDatabase.deleteDatabase(mDatabaseHelper.getDatabaseFile()); + void deleteFileForTests() { + synchronized(this) { + mPackageStatusFile.delete(); + } } /** @@ -93,48 +103,60 @@ final class PackageStatusStorage { synchronized (this) { try { return getPackageStatusInternal(); - } catch (IllegalArgumentException e) { - // This means that data exists in the table but it was bad. - Slog.e(TAG, "Package status invalid, resetting and retrying", e); + } catch (ParseException e) { + // This means that data exists in the file but it was bad. + Slog.e(LOG_TAG, "Package status invalid, resetting and retrying", e); // Reset the storage so it is in a good state again. - mDatabaseHelper.recoverFromBadData(); - return getPackageStatusInternal(); + recoverFromBadData(e); + try { + return getPackageStatusInternal(); + } catch (ParseException e2) { + throw new IllegalStateException("Recovery from bad file failed", e2); + } } } } - private PackageStatus getPackageStatusInternal() { - String[] columns = { - COLUMN_CHECK_STATUS, COLUMN_UPDATE_APP_VERSION, COLUMN_DATA_APP_VERSION - }; - Cursor cursor = mDatabaseHelper.getReadableDatabase() - .query(TABLE, columns, COLUMN_ID + " = ?", - new String[] { Integer.toString(SINGLETON_ID) }, - null /* groupBy */, null /* having */, null /* orderBy */); - if (cursor.getCount() != 1) { - Slog.e(TAG, "Unable to find package status from package status row. Rows returned: " - + cursor.getCount()); - return null; + private PackageStatus getPackageStatusInternal() throws ParseException { + try (FileInputStream fis = mPackageStatusFile.openRead()) { + XmlPullParser parser = parseToPackageStatusTag(fis); + Integer checkStatus = getNullableIntAttribute(parser, ATTRIBUTE_CHECK_STATUS); + if (checkStatus == null) { + return null; + } + int updateAppVersion = getIntAttribute(parser, ATTRIBUTE_UPDATE_APP_VERSION); + int dataAppVersion = getIntAttribute(parser, ATTRIBUTE_DATA_APP_VERSION); + return new PackageStatus(checkStatus, + new PackageVersions(updateAppVersion, dataAppVersion)); + } catch (IOException e) { + ParseException e2 = new ParseException("Error reading package status", 0); + e2.initCause(e); + throw e2; } - cursor.moveToFirst(); + } - // Determine check status. - if (cursor.isNull(0)) { - // This is normal the first time getPackageStatus() is called, or after - // resetCheckState(). - return null; + // Callers should be synchronized(this). + private int recoverFromBadData(Exception cause) { + mPackageStatusFile.delete(); + try { + return insertInitialPackageStatus(); + } catch (IOException e) { + IllegalStateException fatal = new IllegalStateException(e); + fatal.addSuppressed(cause); + throw fatal; } - int checkStatus = cursor.getInt(0); + } - // Determine package version. - if (cursor.isNull(1) || cursor.isNull(2)) { - Slog.e(TAG, "Package version information unexpectedly null"); - return null; - } - PackageVersions packageVersions = new PackageVersions(cursor.getInt(1), cursor.getInt(2)); + /** Insert the initial data, returning the optimistic lock ID */ + private int insertInitialPackageStatus() throws IOException { + // Doesn't matter what it is, but we avoid the obvious starting value each time the data + // is reset to ensure that old tokens are unlikely to work. + final int initialOptimisticLockId = (int) System.currentTimeMillis(); - return new PackageStatus(checkStatus, packageVersions); + writePackageStatusInternal(null /* status */, initialOptimisticLockId, + null /* packageVersions */); + return initialOptimisticLockId; } /** @@ -147,23 +169,29 @@ final class PackageStatusStorage { } synchronized (this) { - Integer optimisticLockId = getCurrentOptimisticLockId(); - if (optimisticLockId == null) { - Slog.w(TAG, "Unable to find optimistic lock ID from package status row"); + int optimisticLockId; + try { + optimisticLockId = getCurrentOptimisticLockId(); + } catch (ParseException e) { + Slog.w(LOG_TAG, "Unable to find optimistic lock ID from package status"); // Recover. - optimisticLockId = mDatabaseHelper.recoverFromBadData(); + optimisticLockId = recoverFromBadData(e); } int newOptimisticLockId = optimisticLockId + 1; - boolean statusRowUpdated = writeStatusRow( - optimisticLockId, newOptimisticLockId, CHECK_STARTED, currentInstalledVersions); - if (!statusRowUpdated) { - Slog.e(TAG, "Unable to update status to CHECK_STARTED in package status row." - + " synchronization failure?"); - return null; + try { + boolean statusUpdated = writePackageStatusWithOptimisticLockCheck( + optimisticLockId, newOptimisticLockId, CHECK_STARTED, + currentInstalledVersions); + if (!statusUpdated) { + throw new IllegalStateException("Unable to update status to CHECK_STARTED." + + " synchronization failure?"); + } + return new CheckToken(newOptimisticLockId, currentInstalledVersions); + } catch (IOException e) { + throw new IllegalStateException(e); } - return new CheckToken(newOptimisticLockId, currentInstalledVersions); } } @@ -172,19 +200,25 @@ final class PackageStatusStorage { */ void resetCheckState() { synchronized(this) { - Integer optimisticLockId = getCurrentOptimisticLockId(); - if (optimisticLockId == null) { - Slog.w(TAG, "resetCheckState: Unable to find optimistic lock ID from package" - + " status row"); + int optimisticLockId; + try { + optimisticLockId = getCurrentOptimisticLockId(); + } catch (ParseException e) { + Slog.w(LOG_TAG, "resetCheckState: Unable to find optimistic lock ID from package" + + " status"); // Attempt to recover the storage state. - optimisticLockId = mDatabaseHelper.recoverFromBadData(); + optimisticLockId = recoverFromBadData(e); } int newOptimisticLockId = optimisticLockId + 1; - if (!writeStatusRow(optimisticLockId, newOptimisticLockId, - null /* status */, null /* packageVersions */)) { - Slog.e(TAG, "resetCheckState: Unable to reset package status row," - + " newOptimisticLockId=" + newOptimisticLockId); + try { + if (!writePackageStatusWithOptimisticLockCheck(optimisticLockId, + newOptimisticLockId, null /* status */, null /* packageVersions */)) { + throw new IllegalStateException("resetCheckState: Unable to reset package" + + " status, newOptimisticLockId=" + newOptimisticLockId); + } + } catch (IOException e) { + throw new IllegalStateException(e); } } } @@ -199,138 +233,146 @@ final class PackageStatusStorage { int optimisticLockId = checkToken.mOptimisticLockId; int newOptimisticLockId = optimisticLockId + 1; int status = succeeded ? CHECK_COMPLETED_SUCCESS : CHECK_COMPLETED_FAILURE; - return writeStatusRow(optimisticLockId, newOptimisticLockId, - status, checkToken.mPackageVersions); + try { + return writePackageStatusWithOptimisticLockCheck(optimisticLockId, + newOptimisticLockId, status, checkToken.mPackageVersions); + } catch (IOException e) { + throw new IllegalStateException(e); + } } } - // Caller should be synchronized(this) - private Integer getCurrentOptimisticLockId() { - final String[] columns = { COLUMN_OPTIMISTIC_LOCK_ID }; - final String querySelection = COLUMN_ID + " = ?"; - final String[] querySelectionArgs = { Integer.toString(SINGLETON_ID) }; - - SQLiteDatabase database = mDatabaseHelper.getReadableDatabase(); - try (Cursor cursor = database.query(TABLE, columns, querySelection, querySelectionArgs, - null /* groupBy */, null /* having */, null /* orderBy */)) { - if (cursor.getCount() != 1) { - Slog.w(TAG, cursor.getCount() + " rows returned, expected exactly one."); - return null; - } - cursor.moveToFirst(); - return cursor.getInt(0); + // Caller should be synchronized(this). + private int getCurrentOptimisticLockId() throws ParseException { + try (FileInputStream fis = mPackageStatusFile.openRead()) { + XmlPullParser parser = parseToPackageStatusTag(fis); + return getIntAttribute(parser, ATTRIBUTE_OPTIMISTIC_LOCK_ID); + } catch (IOException e) { + ParseException e2 = new ParseException("Unable to read file", 0); + e2.initCause(e); + throw e2; } } - // Caller should be synchronized(this) - private boolean writeStatusRow(int optimisticLockId, int newOptimisticLockId, Integer status, - PackageVersions packageVersions) { - if ((status == null) != (packageVersions == null)) { - throw new IllegalArgumentException( - "Provide both status and packageVersions, or neither."); + /** Returns a parser or throws ParseException, never returns null. */ + private static XmlPullParser parseToPackageStatusTag(FileInputStream fis) + throws ParseException { + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(fis, StandardCharsets.UTF_8.name()); + int type; + while ((type = parser.next()) != END_DOCUMENT) { + final String tag = parser.getName(); + if (type == START_TAG && TAG_PACKAGE_STATUS.equals(tag)) { + return parser; + } + } + throw new ParseException("Unable to find " + TAG_PACKAGE_STATUS + " tag", 0); + } catch (XmlPullParserException e) { + throw new IllegalStateException("Unable to configure parser", e); + } catch (IOException e) { + ParseException e2 = new ParseException("Error reading XML", 0); + e.initCause(e); + throw e2; } + } - SQLiteDatabase database = mDatabaseHelper.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put(COLUMN_OPTIMISTIC_LOCK_ID, newOptimisticLockId); - if (status == null) { - values.putNull(COLUMN_CHECK_STATUS); - values.put(COLUMN_UPDATE_APP_VERSION, UNKNOWN_PACKAGE_VERSION); - values.put(COLUMN_DATA_APP_VERSION, UNKNOWN_PACKAGE_VERSION); - } else { - values.put(COLUMN_CHECK_STATUS, status); - values.put(COLUMN_UPDATE_APP_VERSION, packageVersions.mUpdateAppVersion); - values.put(COLUMN_DATA_APP_VERSION, packageVersions.mDataAppVersion); - } + // Caller should be synchronized(this). + private boolean writePackageStatusWithOptimisticLockCheck(int optimisticLockId, + int newOptimisticLockId, Integer status, PackageVersions packageVersions) + throws IOException { - String updateSelection = COLUMN_ID + " = ? AND " + COLUMN_OPTIMISTIC_LOCK_ID + " = ?"; - String[] updateSelectionArgs = { - Integer.toString(SINGLETON_ID), Integer.toString(optimisticLockId) - }; - int count = database.update(TABLE, values, updateSelection, updateSelectionArgs); - if (count > 1) { - // This has to be because of corruption: there should only ever be one row. - Slog.w(TAG, "writeStatusRow: " + count + " rows updated, expected exactly one."); - // Reset the table. - mDatabaseHelper.recoverFromBadData(); + int currentOptimisticLockId; + try { + currentOptimisticLockId = getCurrentOptimisticLockId(); + if (currentOptimisticLockId != optimisticLockId) { + return false; + } + } catch (ParseException e) { + recoverFromBadData(e); + return false; } - // 1 is the success case. 0 rows updated means the row is missing or the optimistic lock ID - // was not as expected, this could be because of corruption but is most likely due to an - // optimistic lock failure. Callers can decide on a case-by-case basis. - return count == 1; - } - - /** Only used during tests to force an empty table. */ - void deleteRowForTests() { - mDatabaseHelper.getWritableDatabase().delete(TABLE, null, null); + writePackageStatusInternal(status, newOptimisticLockId, packageVersions); + return true; } - /** Only used during tests to force a known table state. */ - public void forceCheckStateForTests(int checkStatus, PackageVersions packageVersions) { - int optimisticLockId = getCurrentOptimisticLockId(); - writeStatusRow(optimisticLockId, optimisticLockId, checkStatus, packageVersions); - } - - static class DatabaseHelper extends SQLiteOpenHelper { - - private final Context mContext; - - public DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - mContext = context; - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE + " (" + - "_id INTEGER PRIMARY KEY," + - COLUMN_OPTIMISTIC_LOCK_ID + " INTEGER NOT NULL," + - COLUMN_CHECK_STATUS + " INTEGER," + - COLUMN_UPDATE_APP_VERSION + " INTEGER NOT NULL," + - COLUMN_DATA_APP_VERSION + " INTEGER NOT NULL" + - ");"); - insertInitialRowState(db); + // Caller should be synchronized(this). + private void writePackageStatusInternal(Integer status, int optimisticLockId, + PackageVersions packageVersions) throws IOException { + if ((status == null) != (packageVersions == null)) { + throw new IllegalArgumentException( + "Provide both status and packageVersions, or neither."); } - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { - // no-op: nothing to upgrade + FileOutputStream fos = null; + try { + fos = mPackageStatusFile.startWrite(); + XmlSerializer serializer = new FastXmlSerializer(); + serializer.setOutput(fos, StandardCharsets.UTF_8.name()); + serializer.startDocument(null /* encoding */, true /* standalone */); + final String namespace = null; + serializer.startTag(namespace, TAG_PACKAGE_STATUS); + String statusAttributeValue = status == null ? "" : Integer.toString(status); + serializer.attribute(namespace, ATTRIBUTE_CHECK_STATUS, statusAttributeValue); + serializer.attribute(namespace, ATTRIBUTE_OPTIMISTIC_LOCK_ID, + Integer.toString(optimisticLockId)); + int updateAppVersion = status == null + ? UNKNOWN_PACKAGE_VERSION : packageVersions.mUpdateAppVersion; + serializer.attribute(namespace, ATTRIBUTE_UPDATE_APP_VERSION, + Integer.toString(updateAppVersion)); + int dataAppVersion = status == null + ? UNKNOWN_PACKAGE_VERSION : packageVersions.mDataAppVersion; + serializer.attribute(namespace, ATTRIBUTE_DATA_APP_VERSION, + Integer.toString(dataAppVersion)); + serializer.endTag(namespace, TAG_PACKAGE_STATUS); + serializer.endDocument(); + serializer.flush(); + mPackageStatusFile.finishWrite(fos); + } catch (IOException e) { + if (fos != null) { + mPackageStatusFile.failWrite(fos); + } + throw e; } - /** Recover the initial data row state, returning the new current optimistic lock ID */ - int recoverFromBadData() { - // Delete the table content. - SQLiteDatabase writableDatabase = getWritableDatabase(); - writableDatabase.delete(TABLE, null /* whereClause */, null /* whereArgs */); + } - // Insert the initial content. - return insertInitialRowState(writableDatabase); + /** Only used during tests to force a known table state. */ + public void forceCheckStateForTests(int checkStatus, PackageVersions packageVersions) { + synchronized (this) { + try { + int optimisticLockId = getCurrentOptimisticLockId(); + writePackageStatusWithOptimisticLockCheck(optimisticLockId, optimisticLockId, + checkStatus, packageVersions); + } catch (IOException | ParseException e) { + throw new IllegalStateException(e); + } } + } - /** Insert the initial data row, returning the optimistic lock ID */ - private static int insertInitialRowState(SQLiteDatabase db) { - // Doesn't matter what it is, but we avoid the obvious starting value each time the row - // is reset to ensure that old tokens are unlikely to work. - final int initialOptimisticLockId = (int) System.currentTimeMillis(); - - // Insert the one row. - ContentValues values = new ContentValues(); - values.put(COLUMN_ID, SINGLETON_ID); - values.put(COLUMN_OPTIMISTIC_LOCK_ID, initialOptimisticLockId); - values.putNull(COLUMN_CHECK_STATUS); - values.put(COLUMN_UPDATE_APP_VERSION, UNKNOWN_PACKAGE_VERSION); - values.put(COLUMN_DATA_APP_VERSION, UNKNOWN_PACKAGE_VERSION); - long id = db.insert(TABLE, null, values); - if (id == -1) { - Slog.w(TAG, "insertInitialRow: could not insert initial row, id=" + id); - return -1; + private static Integer getNullableIntAttribute(XmlPullParser parser, String attributeName) + throws ParseException { + String attributeValue = parser.getAttributeValue(null, attributeName); + try { + if (attributeValue == null) { + throw new ParseException("Attribute " + attributeName + " missing", 0); + } else if (attributeValue.isEmpty()) { + return null; } - return initialOptimisticLockId; + return Integer.parseInt(attributeValue); + } catch (NumberFormatException e) { + throw new ParseException( + "Bad integer for attributeName=" + attributeName + ": " + attributeValue, 0); } + } - File getDatabaseFile() { - return mContext.getDatabasePath(DATABASE_NAME); + private static int getIntAttribute(XmlPullParser parser, String attributeName) + throws ParseException { + Integer value = getNullableIntAttribute(parser, attributeName); + if (value == null) { + throw new ParseException("Missing attribute " + attributeName, 0); } + return value; } } diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java index 8abf7df9952b..f9af2eae92cd 100644 --- a/services/core/java/com/android/server/timezone/PackageTracker.java +++ b/services/core/java/com/android/server/timezone/PackageTracker.java @@ -21,9 +21,12 @@ import com.android.internal.annotations.VisibleForTesting; import android.app.timezone.RulesUpdaterContract; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Environment; import android.provider.TimeZoneRulesDataContract; import android.util.Slog; +import java.io.File; + /** * Monitors the installed applications associated with time zone updates. If the app packages are * updated it indicates there <em>might</em> be a time zone rules update to apply so a targeted @@ -81,11 +84,17 @@ public class PackageTracker implements IntentHelper.Listener { /** Creates the {@link PackageTracker} for normal use. */ static PackageTracker create(Context context) { PackageTrackerHelperImpl helperImpl = new PackageTrackerHelperImpl(context); + // TODO(nfuller): Switch to FileUtils.createDir() when available. http://b/31008728 + File storageDir = new File(Environment.getDataSystemDirectory(), "timezone"); + if (!storageDir.exists()) { + storageDir.mkdir(); + } + return new PackageTracker( helperImpl /* clock */, helperImpl /* configHelper */, helperImpl /* packageManagerHelper */, - new PackageStatusStorage(context), + new PackageStatusStorage(storageDir), new IntentHelperImpl(context)); } diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java index e085270fc3a4..dd56072372af 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java @@ -21,10 +21,11 @@ import org.junit.Before; import org.junit.Test; import android.content.Context; -import android.database.sqlite.SQLiteDatabase; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; +import java.io.File; + import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -40,15 +41,16 @@ public class PackageStatusStorageTest { @Before public void setUp() throws Exception { Context context = InstrumentationRegistry.getContext(); + File dataDir = context.getFilesDir(); // Using the instrumentation context means the database is created in a test app-specific // directory. - mPackageStatusStorage = new PackageStatusStorage(context); + mPackageStatusStorage = new PackageStatusStorage(dataDir); } @After public void tearDown() throws Exception { - mPackageStatusStorage.deleteDatabaseForTests(); + mPackageStatusStorage.deleteFileForTests(); } @Test @@ -90,7 +92,7 @@ public class PackageStatusStorageTest { } @Test - public void generateCheckToken_missingRowBehavior() { + public void generateCheckToken_missingFileBehavior() { // Assert initial state. assertNull(mPackageStatusStorage.getPackageStatus()); @@ -100,15 +102,15 @@ public class PackageStatusStorageTest { // There should now be state. assertNotNull(mPackageStatusStorage.getPackageStatus()); - // Corrupt the table by removing the one row. - mPackageStatusStorage.deleteRowForTests(); + // Corrupt the data by removing the file. + mPackageStatusStorage.deleteFileForTests(); // Check that generateCheckToken recovers. assertNotNull(mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS)); } @Test - public void getPackageStatus_missingRowBehavior() { + public void getPackageStatus_missingFileBehavior() { // Assert initial state. assertNull(mPackageStatusStorage.getPackageStatus()); @@ -118,14 +120,14 @@ public class PackageStatusStorageTest { // There should now be a state. assertNotNull(mPackageStatusStorage.getPackageStatus()); - // Corrupt the table by removing the one row. - mPackageStatusStorage.deleteRowForTests(); + // Corrupt the data by removing the file. + mPackageStatusStorage.deleteFileForTests(); assertNull(mPackageStatusStorage.getPackageStatus()); } @Test - public void markChecked_missingRowBehavior() { + public void markChecked_missingFileBehavior() { // Assert initial state. CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); assertNotNull(token1); @@ -133,10 +135,10 @@ public class PackageStatusStorageTest { // There should now be a state. assertNotNull(mPackageStatusStorage.getPackageStatus()); - // Corrupt the table by removing the one row. - mPackageStatusStorage.deleteRowForTests(); + // Corrupt the data by removing the file. + mPackageStatusStorage.deleteFileForTests(); - // The missing row should mean token1 is now considered invalid, so we should get a false. + // The missing file should mean token1 is now considered invalid, so we should get a false. assertFalse(mPackageStatusStorage.markChecked(token1, true /* succeeded */)); // The storage should have recovered and we should be able to carry on like before. diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java index 45b0af37f9e3..4c7680b1edef 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java @@ -71,7 +71,7 @@ public class PackageTrackerTest { // Using the instrumentation context means the database is created in a test app-specific // directory. We can use the real thing for this test. - mPackageStatusStorage = new PackageStatusStorage(context); + mPackageStatusStorage = new PackageStatusStorage(context.getFilesDir()); // For other interactions with the Android framework we create a fake object. mFakeIntentHelper = new FakeIntentHelper(); @@ -88,7 +88,7 @@ public class PackageTrackerTest { @After public void tearDown() throws Exception { if (mPackageStatusStorage != null) { - mPackageStatusStorage.deleteDatabaseForTests(); + mPackageStatusStorage.deleteFileForTests(); } } |