diff --git a/library/core/src/main/java/com/google/android/exoplayer2/database/ExoDatabaseProvider.java b/library/core/src/main/java/com/google/android/exoplayer2/database/ExoDatabaseProvider.java index ece8e57ae7..32dda5965c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/database/ExoDatabaseProvider.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/database/ExoDatabaseProvider.java @@ -16,20 +16,16 @@ package com.google.android.exoplayer2.database; import android.content.Context; -import android.content.ContextWrapper; import android.database.Cursor; -import android.database.DatabaseErrorHandler; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; -import android.support.annotation.Nullable; import com.google.android.exoplayer2.util.Log; -import java.io.File; /** * An {@link SQLiteOpenHelper} that provides instances of a standalone ExoPlayer database. * - *
Suitable for use by applications that do not already have their own database, or which would + *
Suitable for use by applications that do not already have their own database, or that would
* prefer to keep ExoPlayer tables isolated in their own database. Other applications should prefer
* to use {@link DefaultDatabaseProvider} with their own {@link SQLiteOpenHelper}.
*/
@@ -51,15 +47,6 @@ public final class ExoDatabaseProvider extends SQLiteOpenHelper implements Datab
super(context.getApplicationContext(), DATABASE_NAME, /* factory= */ null, VERSION);
}
- /**
- * Provides instances of the database located at the specified file.
- *
- * @param file The database file.
- */
- public ExoDatabaseProvider(File file) {
- super(new DatabaseFileProvidingContext(file), file.getName(), /* factory= */ null, VERSION);
- }
-
@Override
public void onCreate(SQLiteDatabase db) {
// Features create their own tables.
@@ -105,48 +92,4 @@ public final class ExoDatabaseProvider extends SQLiteOpenHelper implements Datab
}
}
}
-
- // TODO: This is fragile. Stop using it if/when SQLiteOpenHelper can be instantiated without a
- // context [Internal ref: b/123351819], or by injecting a Context into all components that need
- // to instantiate an ExoDatabaseProvider.
- /** A {@link Context} that implements methods called by {@link SQLiteOpenHelper}. */
- private static class DatabaseFileProvidingContext extends ContextWrapper {
-
- private final File file;
-
- @SuppressWarnings("nullness:argument.type.incompatible")
- public DatabaseFileProvidingContext(File file) {
- super(/* base= */ null);
- this.file = file;
- }
-
- @Override
- public File getDatabasePath(String name) {
- return file;
- }
-
- @Override
- public SQLiteDatabase openOrCreateDatabase(
- String name, int mode, SQLiteDatabase.CursorFactory factory) {
- return openOrCreateDatabase(name, mode, factory, /* errorHandler= */ null);
- }
-
- @Override
- @SuppressWarnings("nullness:argument.type.incompatible")
- public SQLiteDatabase openOrCreateDatabase(
- String name,
- int mode,
- SQLiteDatabase.CursorFactory factory,
- @Nullable DatabaseErrorHandler errorHandler) {
- File databasePath = getDatabasePath(name);
- int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
- if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
- flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
- }
- if ((mode & MODE_NO_LOCALIZED_COLLATORS) != 0) {
- flags |= SQLiteDatabase.NO_LOCALIZED_COLLATORS;
- }
- return SQLiteDatabase.openDatabase(databasePath.getPath(), factory, flags, errorHandler);
- }
- }
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/database/VersionTable.java b/library/core/src/main/java/com/google/android/exoplayer2/database/VersionTable.java
index cdcca7a350..471b7706ca 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/database/VersionTable.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/database/VersionTable.java
@@ -45,6 +45,8 @@ public final class VersionTable {
private static final String COLUMN_FEATURE = "feature";
private static final String COLUMN_VERSION = "version";
+ private static final String WHERE_FEATURE_EQUALS = COLUMN_FEATURE + " = ?";
+
private static final String SQL_CREATE_TABLE_IF_NOT_EXISTS =
"CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME
@@ -62,7 +64,7 @@ public final class VersionTable {
private VersionTable() {}
/**
- * Sets the version of tables belonging to the specified feature.
+ * Sets the version of the specified feature.
*
* @param writableDatabase The database to update.
* @param feature The feature.
@@ -78,8 +80,21 @@ public final class VersionTable {
}
/**
- * Returns the version of tables belonging to the specified feature, or {@link #VERSION_UNSET} if
- * no version information is available.
+ * Removes the version of the specified feature.
+ *
+ * @param writableDatabase The database to update.
+ * @param feature The feature.
+ */
+ public static void removeVersion(SQLiteDatabase writableDatabase, @Feature int feature) {
+ if (!tableExists(writableDatabase, TABLE_NAME)) {
+ return;
+ }
+ writableDatabase.delete(TABLE_NAME, WHERE_FEATURE_EQUALS, featureArgument(feature));
+ }
+
+ /**
+ * Returns the version of the specified feature, or {@link #VERSION_UNSET} if no version
+ * information is available.
*
* @param database The database to query.
* @param feature The feature.
@@ -88,14 +103,12 @@ public final class VersionTable {
if (!tableExists(database, TABLE_NAME)) {
return VERSION_UNSET;
}
- String selection = COLUMN_FEATURE + " = ?";
- String[] selectionArgs = {Integer.toString(feature)};
try (Cursor cursor =
database.query(
TABLE_NAME,
new String[] {COLUMN_VERSION},
- selection,
- selectionArgs,
+ WHERE_FEATURE_EQUALS,
+ featureArgument(feature),
/* groupBy= */ null,
/* having= */ null,
/* orderBy= */ null)) {
@@ -114,4 +127,8 @@ public final class VersionTable {
readableDatabase, "sqlite_master", "tbl_name = ?", new String[] {tableName});
return count > 0;
}
+
+ private static String[] featureArgument(int feature) {
+ return new String[] {Integer.toString(feature)};
+ }
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java
index c30260b11b..37b0f43f8b 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java
@@ -73,7 +73,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
private static final int COLUMN_INDEX_STREAM_KEYS = 14;
private static final int COLUMN_INDEX_CUSTOM_METADATA = 15;
- private static final String COLUMN_SELECTION_ID = COLUMN_ID + " = ?";
+ private static final String WHERE_ID_EQUALS = COLUMN_ID + " = ?";
private static final String[] COLUMNS =
new String[] {
@@ -152,7 +152,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
@Nullable
public DownloadState getDownloadState(String id) {
ensureInitialized();
- try (Cursor cursor = getCursor(COLUMN_SELECTION_ID, new String[] {id})) {
+ try (Cursor cursor = getCursor(WHERE_ID_EQUALS, new String[] {id})) {
if (cursor.getCount() == 0) {
return null;
}
@@ -210,9 +210,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
@Override
public void removeDownloadState(String id) {
ensureInitialized();
- databaseProvider
- .getWritableDatabase()
- .delete(TABLE_NAME, COLUMN_SELECTION_ID, new String[] {id});
+ databaseProvider.getWritableDatabase().delete(TABLE_NAME, WHERE_ID_EQUALS, new String[] {id});
}
private void ensureInitialized() {
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java
index b22645c9d2..e7289bf29e 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java
@@ -24,7 +24,6 @@ import android.support.annotation.VisibleForTesting;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.google.android.exoplayer2.database.DatabaseProvider;
-import com.google.android.exoplayer2.database.ExoDatabaseProvider;
import com.google.android.exoplayer2.database.VersionTable;
import com.google.android.exoplayer2.upstream.cache.Cache.CacheException;
import com.google.android.exoplayer2.util.Assertions;
@@ -154,9 +153,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
Storage atomicFileStorage =
new AtomicFileStorage(
new File(cacheDir, FILE_NAME_ATOMIC), random, encrypt, cipher, secretKeySpec);
- // Storage sqliteStorage =
- // new SQLiteStorage(
- // new File(cacheDir, FILE_NAME_DATABASE), random, encrypt, cipher, secretKeySpec);
+ // Storage sqliteStorage = new SQLiteStorage(databaseProvider);
storage = atomicFileStorage;
previousStorage = null;
}
@@ -170,7 +167,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
storage.storeFully(keyToContent);
} catch (CacheException e) {
// We failed to copy into current storage, so keep using previous storage.
- storage.release();
storage = previousStorage;
previousStorage = null;
}
@@ -179,7 +175,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
loadFrom(storage);
}
if (previousStorage != null) {
- previousStorage.release(/* delete= */ true);
+ previousStorage.delete();
previousStorage = null;
}
}
@@ -195,14 +191,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
removedIds.clear();
}
- /** Releases any underlying resources. */
- public void release() {
- storage.release();
- if (previousStorage != null) {
- previousStorage.release();
- }
- }
-
/**
* Adds the given key to the index if it isn't there already.
*
@@ -396,13 +384,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Returns whether the persisted index exists. */
boolean exists();
- /** Releases any held resources. */
- default void release() {
- release(/* delete= */ false);
- }
-
- /** Releases and held resources and optionally deletes the persisted index. */
- void release(boolean delete);
+ /** Deletes the persisted index. */
+ void delete();
/**
* Loads the persisted index into {@code content} and {@code idToKey}, creating it if it doesn't
@@ -479,10 +462,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
@Override
- public void release(boolean delete) {
- if (delete) {
- atomicFile.delete();
- }
+ public void delete() {
+ atomicFile.delete();
}
@Override
@@ -672,26 +653,22 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
/** {@link Storage} implementation that uses an SQL database. */
- // TODO:
- // 1. Implement upgrade/downgrade paths from/to AtomicFileStorage.
- // 2. If encryption is enabled having previously written data, decide whether we need to rewrite
- // the entire table. Currently this implementation only encrypts new and updated entries.
private static final class SQLiteStorage implements Storage {
private static final String TABLE_NAME = DatabaseProvider.TABLE_PREFIX + "CacheContentMetadata";
private static final int TABLE_VERSION = 1;
private static final String COLUMN_ID = "id";
- private static final String COLUMN_FLAGS = "flags";
- private static final String COLUMN_DATA = "data";
+ private static final String COLUMN_KEY = "key";
+ private static final String COLUMN_METADATA = "metadata";
private static final int COLUMN_INDEX_ID = 0;
- private static final int COLUMN_INDEX_FLAGS = 1;
- private static final int COLUMN_INDEX_DATA = 2;
+ private static final int COLUMN_INDEX_KEY = 1;
+ private static final int COLUMN_INDEX_METADATA = 2;
- private static final String COLUMN_SELECTION_ID = COLUMN_ID + " = ?";
+ private static final String WHERE_ID_EQUALS = COLUMN_ID + " = ?";
- private static final String[] COLUMNS = new String[] {COLUMN_ID, COLUMN_FLAGS, COLUMN_DATA};
+ private static final String[] COLUMNS = new String[] {COLUMN_ID, COLUMN_KEY, COLUMN_METADATA};
private static final String SQL_DROP_TABLE_IF_EXISTS = "DROP TABLE IF EXISTS " + TABLE_NAME;
private static final String SQL_CREATE_TABLE =
@@ -700,52 +677,36 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
+ " ("
+ COLUMN_ID
+ " INTEGER PRIMARY KEY NOT NULL,"
- + COLUMN_FLAGS
- + " INTEGER NOT NULL,"
- + COLUMN_DATA
+ + COLUMN_KEY
+ + " TEXT NOT NULL,"
+ + COLUMN_METADATA
+ " BLOB NOT NULL)";
- private static final int FLAG_ENCRYPTED = 1;
-
- private final File file;
- private final Random random;
- private final boolean encrypt;
- @Nullable private final Cipher cipher;
- @Nullable private final SecretKeySpec secretKeySpec;
- private final ExoDatabaseProvider databaseProvider;
+ private final DatabaseProvider databaseProvider;
private final SparseArray