Prepare SimpleCache for 2.10.0 release

- Expose constructors that take DatabaseProvider. Deprecate those
  that do not.
- Expose Cache.getUid. This will likely be used for naming of the
  tables accessed by DefaultDownloadIndex .

PiperOrigin-RevId: 243637786
This commit is contained in:
olly 2019-04-15 18:09:22 +01:00 committed by AquilesCanta
parent 45348a97a9
commit 9c759a867b
3 changed files with 78 additions and 34 deletions

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.demo;
import android.app.Application; import android.app.Application;
import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.database.DatabaseProvider;
import com.google.android.exoplayer2.database.ExoDatabaseProvider; import com.google.android.exoplayer2.database.ExoDatabaseProvider;
import com.google.android.exoplayer2.offline.ActionFileUpgradeUtil; import com.google.android.exoplayer2.offline.ActionFileUpgradeUtil;
import com.google.android.exoplayer2.offline.DefaultDownloadIndex; import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
@ -52,6 +53,7 @@ public class DemoApplication extends Application {
protected String userAgent; protected String userAgent;
private DatabaseProvider databaseProvider;
private File downloadDirectory; private File downloadDirectory;
private Cache downloadCache; private Cache downloadCache;
private DownloadManager downloadManager; private DownloadManager downloadManager;
@ -105,14 +107,15 @@ public class DemoApplication extends Application {
protected synchronized Cache getDownloadCache() { protected synchronized Cache getDownloadCache() {
if (downloadCache == null) { if (downloadCache == null) {
File downloadContentDirectory = new File(getDownloadDirectory(), DOWNLOAD_CONTENT_DIRECTORY); File downloadContentDirectory = new File(getDownloadDirectory(), DOWNLOAD_CONTENT_DIRECTORY);
downloadCache = new SimpleCache(downloadContentDirectory, new NoOpCacheEvictor()); downloadCache =
new SimpleCache(downloadContentDirectory, new NoOpCacheEvictor(), getDatabaseProvider());
} }
return downloadCache; return downloadCache;
} }
private synchronized void initDownloadManager() { private synchronized void initDownloadManager() {
if (downloadManager == null) { if (downloadManager == null) {
DefaultDownloadIndex downloadIndex = new DefaultDownloadIndex(new ExoDatabaseProvider(this)); DefaultDownloadIndex downloadIndex = new DefaultDownloadIndex(getDatabaseProvider());
upgradeActionFile(DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex); upgradeActionFile(DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex);
upgradeActionFile(DOWNLOAD_ACTION_FILE, downloadIndex); upgradeActionFile(DOWNLOAD_ACTION_FILE, downloadIndex);
DownloaderConstructorHelper downloaderConstructorHelper = DownloaderConstructorHelper downloaderConstructorHelper =
@ -143,6 +146,13 @@ public class DemoApplication extends Application {
} }
} }
private DatabaseProvider getDatabaseProvider() {
if (databaseProvider == null) {
databaseProvider = new ExoDatabaseProvider(this);
}
return databaseProvider;
}
private File getDownloadDirectory() { private File getDownloadDirectory() {
if (downloadDirectory == null) { if (downloadDirectory == null) {
downloadDirectory = getExternalFilesDir(null); downloadDirectory = getExternalFilesDir(null);

View File

@ -82,6 +82,22 @@ public interface Cache {
} }
} }
/**
* Returned by {@link #getUid()} if initialization failed before the unique identifier was read or
* generated.
*/
long UID_UNSET = -1;
/**
* Returns a non-negative unique identifier for the cache, or {@link #UID_UNSET} if initialization
* failed before the unique identifier was determined.
*
* <p>Implementations are expected to generate and store the unique identifier alongside the
* cached content. If the location of the cache is deleted or swapped, it is expected that a new
* unique identifier will be generated when the cache is recreated.
*/
long getUid();
/** /**
* Releases the cache. This method must be called when the cache is no longer required. The cache * Releases the cache. This method must be called when the cache is no longer required. The cache
* must not be used after calling this method. * must not be used after calling this method.

View File

@ -133,7 +133,7 @@ public final class SimpleCache implements Cache {
// Make a best effort to read the cache UID and delete associated index data before deleting // Make a best effort to read the cache UID and delete associated index data before deleting
// cache directory itself. // cache directory itself.
long uid = loadUid(files); long uid = loadUid(files);
if (uid != -1) { if (uid != UID_UNSET) {
try { try {
CacheFileMetadataIndex.delete(databaseProvider, uid); CacheFileMetadataIndex.delete(databaseProvider, uid);
} catch (DatabaseIOException e) { } catch (DatabaseIOException e) {
@ -155,8 +155,11 @@ public final class SimpleCache implements Cache {
* the directory cannot be used to store other files. * the directory cannot be used to store other files.
* *
* @param cacheDir A dedicated cache directory. * @param cacheDir A dedicated cache directory.
* @param evictor The evictor to be used. * @param evictor The evictor to be used. For download use cases where cache eviction should not
* occur, use {@link NoOpCacheEvictor}.
* @deprecated Use a constructor that takes a {@link DatabaseProvider} for improved performance.
*/ */
@Deprecated
public SimpleCache(File cacheDir, CacheEvictor evictor) { public SimpleCache(File cacheDir, CacheEvictor evictor) {
this(cacheDir, evictor, null, false); this(cacheDir, evictor, null, false);
} }
@ -166,10 +169,13 @@ public final class SimpleCache implements Cache {
* the directory cannot be used to store other files. * the directory cannot be used to store other files.
* *
* @param cacheDir A dedicated cache directory. * @param cacheDir A dedicated cache directory.
* @param evictor The evictor to be used. * @param evictor The evictor to be used. For download use cases where cache eviction should not
* occur, use {@link NoOpCacheEvictor}.
* @param secretKey If not null, cache keys will be stored encrypted on filesystem using AES/CBC. * @param secretKey If not null, cache keys will be stored encrypted on filesystem using AES/CBC.
* The key must be 16 bytes long. * The key must be 16 bytes long.
* @deprecated Use a constructor that takes a {@link DatabaseProvider} for improved performance.
*/ */
@Deprecated
public SimpleCache(File cacheDir, CacheEvictor evictor, @Nullable byte[] secretKey) { public SimpleCache(File cacheDir, CacheEvictor evictor, @Nullable byte[] secretKey) {
this(cacheDir, evictor, secretKey, secretKey != null); this(cacheDir, evictor, secretKey, secretKey != null);
} }
@ -179,12 +185,15 @@ public final class SimpleCache implements Cache {
* the directory cannot be used to store other files. * the directory cannot be used to store other files.
* *
* @param cacheDir A dedicated cache directory. * @param cacheDir A dedicated cache directory.
* @param evictor The evictor to be used. * @param evictor The evictor to be used. For download use cases where cache eviction should not
* occur, use {@link NoOpCacheEvictor}.
* @param secretKey If not null, cache keys will be stored encrypted on filesystem using AES/CBC. * @param secretKey If not null, cache keys will be stored encrypted on filesystem using AES/CBC.
* The key must be 16 bytes long. * The key must be 16 bytes long.
* @param encrypt Whether the index will be encrypted when written. Must be false if {@code * @param encrypt Whether the index will be encrypted when written. Must be false if {@code
* secretKey} is null. * secretKey} is null.
* @deprecated Use a constructor that takes a {@link DatabaseProvider} for improved performance.
*/ */
@Deprecated
public SimpleCache( public SimpleCache(
File cacheDir, CacheEvictor evictor, @Nullable byte[] secretKey, boolean encrypt) { File cacheDir, CacheEvictor evictor, @Nullable byte[] secretKey, boolean encrypt) {
this( this(
@ -196,26 +205,45 @@ public final class SimpleCache implements Cache {
/* preferLegacyIndex= */ true); /* preferLegacyIndex= */ true);
} }
// TODO: Make public and consider a constructor that takes DatabaseProvider but not legacy args. /**
* Constructs the cache. The cache will delete any unrecognized files from the directory. Hence
* the directory cannot be used to store other files.
*
* @param cacheDir A dedicated cache directory.
* @param evictor The evictor to be used. For download use cases where cache eviction should not
* occur, use {@link NoOpCacheEvictor}.
* @param databaseProvider Provides the database in which the cache index is stored.
*/
public SimpleCache(File cacheDir, CacheEvictor evictor, DatabaseProvider databaseProvider) {
this(
cacheDir,
evictor,
databaseProvider,
/* legacyIndexSecretKey= */ null,
/* legacyIndexEncrypt= */ false,
/* preferLegacyIndex= */ false);
}
/** /**
* Constructs the cache. The cache will delete any unrecognized files from the cache directory. * Constructs the cache. The cache will delete any unrecognized files from the cache directory.
* Hence the directory cannot be used to store other files. * Hence the directory cannot be used to store other files.
* *
* @param cacheDir A dedicated cache directory. * @param cacheDir A dedicated cache directory.
* @param evictor The evictor to be used. * @param evictor The evictor to be used. For download use cases where cache eviction should not
* occur, use {@link NoOpCacheEvictor}.
* @param databaseProvider Provides the database in which the cache index is stored, or {@code * @param databaseProvider Provides the database in which the cache index is stored, or {@code
* null} to use a legacy index. Using the database index is highly recommended for performance * null} to use a legacy index. Using a database index is highly recommended for performance
* reasons. * reasons.
* @param legacyIndexSecretKey A 16 byte AES key for reading, and optionally writing, the legacy * @param legacyIndexSecretKey A 16 byte AES key for reading, and optionally writing, the legacy
* index. Not used by the database index, however should still be provided when using the * index. Not used by the database index, however should still be provided when using the
* database index in cases where upgrading from the legacy index may be necessary. * database index in cases where upgrading from the legacy index may be necessary.
* @param legacyIndexEncrypt Whether to encrypt when writing to the legacy index. Must be false if * @param legacyIndexEncrypt Whether to encrypt when writing to the legacy index. Must be {@code
* {@code legacyIndexSecretKey} is null. Not used by the database index. * false} if {@code legacyIndexSecretKey} is {@code null}. Not used by the database index.
* @param preferLegacyIndex Whether to use the legacy index even if a {@code databaseProvider} is * @param preferLegacyIndex Whether to use the legacy index even if a {@code databaseProvider} is
* provided. Should be {@code false} in most cases. Setting this to {@code true} is only * provided. Should be {@code false} in nearly all cases. Setting this to {@code true} is only
* useful for downgrading from the database index back to the legacy index. * useful for downgrading from the database index back to the legacy index.
*/ */
/* package */ SimpleCache( public SimpleCache(
File cacheDir, File cacheDir,
CacheEvictor evictor, CacheEvictor evictor,
@Nullable DatabaseProvider databaseProvider, @Nullable DatabaseProvider databaseProvider,
@ -236,15 +264,6 @@ public final class SimpleCache implements Cache {
: null); : null);
} }
/**
* Constructs the cache. The cache will delete any unrecognized files from the directory. Hence
* the directory cannot be used to store other files.
*
* @param cacheDir A dedicated cache directory.
* @param evictor The evictor to be used.
* @param contentIndex The content index to be used.
* @param fileIndex The file index to be used.
*/
/* package */ SimpleCache( /* package */ SimpleCache(
File cacheDir, File cacheDir,
CacheEvictor evictor, CacheEvictor evictor,
@ -260,7 +279,7 @@ public final class SimpleCache implements Cache {
this.fileIndex = fileIndex; this.fileIndex = fileIndex;
listeners = new HashMap<>(); listeners = new HashMap<>();
random = new Random(); random = new Random();
uid = -1; uid = UID_UNSET;
// Start cache initialization. // Start cache initialization.
final ConditionVariable conditionVariable = new ConditionVariable(); final ConditionVariable conditionVariable = new ConditionVariable();
@ -288,6 +307,11 @@ public final class SimpleCache implements Cache {
} }
} }
@Override
public synchronized long getUid() {
return uid;
}
@Override @Override
public synchronized void release() { public synchronized void release() {
if (released) { if (released) {
@ -529,11 +553,6 @@ public final class SimpleCache implements Cache {
return contentIndex.getContentMetadata(key); return contentIndex.getContentMetadata(key);
} }
/** Returns the non-negative cache UID, or -1 if cache initialization failed. */
/* package */ synchronized long getUid() {
return uid;
}
/** /**
* Returns the cache {@link SimpleCacheSpan} corresponding to the provided lookup {@link * Returns the cache {@link SimpleCacheSpan} corresponding to the provided lookup {@link
* SimpleCacheSpan}. * SimpleCacheSpan}.
@ -584,15 +603,14 @@ public final class SimpleCache implements Cache {
} }
uid = loadUid(files); uid = loadUid(files);
if (uid == -1) { if (uid == UID_UNSET) {
try { try {
uid = createUid(cacheDir); uid = createUid(cacheDir);
} catch (IOException e) { } catch (IOException e) {
String message = "Failed to create cache UID: " + cacheDir; String message = "Failed to create cache UID: " + cacheDir;
Log.e(TAG, message, e); Log.e(TAG, message, e);
// TODO: Reinstate this only when a database index is used [Internal ref: b/128933265]. initializationException = new CacheException(message, e);
// initializationException = new CacheException(message, e); return;
// return;
} }
} }
@ -756,7 +774,7 @@ public final class SimpleCache implements Cache {
* Loads the cache UID from the files belonging to the root directory. * Loads the cache UID from the files belonging to the root directory.
* *
* @param files The files belonging to the root directory. * @param files The files belonging to the root directory.
* @return The loaded UID, or -1 if a UID has not yet been created. * @return The loaded UID, or {@link #UID_UNSET} if a UID has not yet been created.
* @throws IOException If there is an error loading or generating the UID. * @throws IOException If there is an error loading or generating the UID.
*/ */
private static long loadUid(File[] files) { private static long loadUid(File[] files) {
@ -772,7 +790,7 @@ public final class SimpleCache implements Cache {
} }
} }
} }
return -1; return UID_UNSET;
} }
@SuppressWarnings("TrulyRandom") @SuppressWarnings("TrulyRandom")