Mark all methods accessing SQLite databases as potentially blocking.

They are all marked with a JavaDoc comment and the @WorkerThread annotation
which is useful if apps are using threading annotations. All other public
methods in the same classes are marked with @AnyThread to avoid the impression
we forgot to annotate them.

PiperOrigin-RevId: 281490301
This commit is contained in:
tonihei 2019-11-20 11:58:57 +00:00 committed by Oliver Woodman
parent fc0aa08d79
commit febfeca2c6
8 changed files with 102 additions and 9 deletions

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.offline;
import static com.google.android.exoplayer2.offline.Download.STATE_QUEUED;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import java.io.File;
import java.io.IOException;
@ -47,6 +48,8 @@ public final class ActionFileUpgradeUtil {
* <p>This method must not be called while the {@link DefaultDownloadIndex} is being used by a
* {@link DownloadManager}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param actionFilePath The action file path.
* @param downloadIdProvider A download ID provider, or {@code null}. If {@code null} then ID of
* each download will be its custom cache key if one is specified, or else its URL.
@ -55,6 +58,7 @@ public final class ActionFileUpgradeUtil {
* @param addNewDownloadsAsCompleted Whether to add new downloads as completed.
* @throws IOException If an error occurs loading or merging the requests.
*/
@WorkerThread
@SuppressWarnings("deprecation")
public static void upgradeAndDelete(
File actionFilePath,

View File

@ -16,14 +16,18 @@
package com.google.android.exoplayer2.offline;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import java.io.IOException;
/** An index of {@link Download Downloads}. */
@WorkerThread
public interface DownloadIndex {
/**
* Returns the {@link Download} with the given {@code id}, or null.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param id ID of a {@link Download}.
* @return The {@link Download} with the given {@code id}, or null if a download state with this
* id doesn't exist.
@ -35,6 +39,8 @@ public interface DownloadIndex {
/**
* Returns a {@link DownloadCursor} to {@link Download}s with the given {@code states}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param states Returns only the {@link Download}s with this states. If empty, returns all.
* @return A cursor to {@link Download}s with the given {@code states}.
* @throws IOException If an error occurs reading the state.

View File

@ -15,14 +15,18 @@
*/
package com.google.android.exoplayer2.offline;
import androidx.annotation.WorkerThread;
import java.io.IOException;
/** A writable index of {@link Download Downloads}. */
@WorkerThread
public interface WritableDownloadIndex extends DownloadIndex {
/**
* Adds or replaces a {@link Download}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param download The {@link Download} to be added.
* @throws IOException If an error occurs setting the state.
*/
@ -32,6 +36,8 @@ public interface WritableDownloadIndex extends DownloadIndex {
* Removes the download with the given ID. Does nothing if a download with the given ID does not
* exist.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param id The ID of the download to remove.
* @throws IOException If an error occurs removing the state.
*/
@ -40,6 +46,8 @@ public interface WritableDownloadIndex extends DownloadIndex {
/**
* Sets all {@link Download#STATE_DOWNLOADING} states to {@link Download#STATE_QUEUED}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @throws IOException If an error occurs updating the state.
*/
void setDownloadingStatesToQueued() throws IOException;
@ -47,6 +55,8 @@ public interface WritableDownloadIndex extends DownloadIndex {
/**
* Sets all states to {@link Download#STATE_REMOVING}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @throws IOException If an error occurs updating the state.
*/
void setStatesToRemoving() throws IOException;
@ -55,6 +65,8 @@ public interface WritableDownloadIndex extends DownloadIndex {
* Sets the stop reason of the downloads in a terminal state ({@link Download#STATE_COMPLETED},
* {@link Download#STATE_FAILED}).
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param stopReason The stop reason.
* @throws IOException If an error occurs updating the state.
*/
@ -65,6 +77,8 @@ public interface WritableDownloadIndex extends DownloadIndex {
* Download#STATE_COMPLETED}, {@link Download#STATE_FAILED}). Does nothing if a download with the
* given ID does not exist, or if it's not in a terminal state.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param id The ID of the download to update.
* @param stopReason The stop reason.
* @throws IOException If an error occurs updating the state.

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.upstream.cache;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import java.io.File;
import java.io.IOException;
@ -100,7 +101,10 @@ public interface 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.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*/
@WorkerThread
void release();
/**
@ -162,23 +166,29 @@ public interface Cache {
* calling {@link #commitFile(File, long)}. When the caller has finished writing, it must release
* the lock by calling {@link #releaseHoleSpan}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param key The key of the data being requested.
* @param position The position of the data being requested.
* @return The {@link CacheSpan}.
* @throws InterruptedException If the thread was interrupted.
* @throws CacheException If an error is encountered.
*/
@WorkerThread
CacheSpan startReadWrite(String key, long position) throws InterruptedException, CacheException;
/**
* Same as {@link #startReadWrite(String, long)}. However, if the cache entry is locked, then
* instead of blocking, this method will return null as the {@link CacheSpan}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param key The key of the data being requested.
* @param position The position of the data being requested.
* @return The {@link CacheSpan}. Or null if the cache entry is locked.
* @throws CacheException If an error is encountered.
*/
@WorkerThread
@Nullable
CacheSpan startReadWriteNonBlocking(String key, long position) throws CacheException;
@ -186,6 +196,8 @@ public interface Cache {
* Obtains a cache file into which data can be written. Must only be called when holding a
* corresponding hole {@link CacheSpan} obtained from {@link #startReadWrite(String, long)}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param key The cache key for the data.
* @param position The starting position of the data.
* @param length The length of the data being written, or {@link C#LENGTH_UNSET} if unknown. Used
@ -193,16 +205,20 @@ public interface Cache {
* @return The file into which data should be written.
* @throws CacheException If an error is encountered.
*/
@WorkerThread
File startFile(String key, long position, long length) throws CacheException;
/**
* Commits a file into the cache. Must only be called when holding a corresponding hole {@link
* CacheSpan} obtained from {@link #startReadWrite(String, long)}
* CacheSpan} obtained from {@link #startReadWrite(String, long)}.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param file A newly written cache file.
* @param length The length of the newly written cache file in bytes.
* @throws CacheException If an error is encountered.
*/
@WorkerThread
void commitFile(File file, long length) throws CacheException;
/**
@ -216,9 +232,12 @@ public interface Cache {
/**
* Removes a cached {@link CacheSpan} from the cache, deleting the underlying file.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param span The {@link CacheSpan} to remove.
* @throws CacheException If an error is encountered.
*/
@WorkerThread
void removeSpan(CacheSpan span) throws CacheException;
/**
@ -247,10 +266,13 @@ public interface Cache {
* Applies {@code mutations} to the {@link ContentMetadata} for the given key. A new {@link
* CachedContent} is added if there isn't one already with the given key.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param key The cache key for the data.
* @param mutations Contains mutations to be applied to the metadata.
* @throws CacheException If an error is encountered.
*/
@WorkerThread
void applyContentMetadataMutations(String key, ContentMetadataMutations mutations)
throws CacheException;

View File

@ -19,6 +19,7 @@ import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.database.DatabaseIOException;
import com.google.android.exoplayer2.database.DatabaseProvider;
import com.google.android.exoplayer2.database.VersionTable;
@ -64,10 +65,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Deletes index data for the specified cache.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param databaseProvider Provides the database in which the index is stored.
* @param uid The cache UID.
* @throws DatabaseIOException If an error occurs deleting the index data.
*/
@WorkerThread
public static void delete(DatabaseProvider databaseProvider, long uid)
throws DatabaseIOException {
String hexUid = Long.toHexString(uid);
@ -96,9 +100,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Initializes the index for the given cache UID.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param uid The cache UID.
* @throws DatabaseIOException If an error occurs initializing the index.
*/
@WorkerThread
public void initialize(long uid) throws DatabaseIOException {
try {
String hexUid = Long.toHexString(uid);
@ -129,9 +136,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* Returns all file metadata keyed by file name. The returned map is mutable and may be modified
* by the caller.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @return The file metadata keyed by file name.
* @throws DatabaseIOException If an error occurs loading the metadata.
*/
@WorkerThread
public Map<String, CacheFileMetadata> getAll() throws DatabaseIOException {
try (Cursor cursor = getCursor()) {
Map<String, CacheFileMetadata> fileMetadata = new HashMap<>(cursor.getCount());
@ -150,11 +160,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Sets metadata for a given file.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param name The name of the file.
* @param length The file length.
* @param lastTouchTimestamp The file last touch timestamp.
* @throws DatabaseIOException If an error occurs setting the metadata.
*/
@WorkerThread
public void set(String name, long length, long lastTouchTimestamp) throws DatabaseIOException {
Assertions.checkNotNull(tableName);
try {
@ -172,9 +185,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Removes metadata.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param name The name of the file whose metadata is to be removed.
* @throws DatabaseIOException If an error occurs removing the metadata.
*/
@WorkerThread
public void remove(String name) throws DatabaseIOException {
Assertions.checkNotNull(tableName);
try {
@ -188,9 +204,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Removes metadata.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param names The names of the files whose metadata is to be removed.
* @throws DatabaseIOException If an error occurs removing the metadata.
*/
@WorkerThread
public void removeAll(Set<String> names) throws DatabaseIOException {
Assertions.checkNotNull(tableName);
try {

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream.cache;
import android.net.Uri;
import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceException;
@ -104,6 +105,8 @@ public final class CacheUtil {
* Caches the data defined by {@code dataSpec}, skipping already cached data. Caching stops early
* if the end of the input is reached.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param dataSpec Defines the data to be cached.
* @param cache A {@link Cache} to store the data.
* @param cacheKeyFactory An optional factory for cache keys.
@ -113,6 +116,7 @@ public final class CacheUtil {
* @throws IOException If an error occurs reading from the source.
* @throws InterruptedException If the thread was interrupted directly or via {@code isCanceled}.
*/
@WorkerThread
public static void cache(
DataSpec dataSpec,
Cache cache,
@ -144,6 +148,8 @@ public final class CacheUtil {
* PriorityTaskManager#add} to register with the manager before calling this method, and to call
* {@link PriorityTaskManager#remove} afterwards to unregister.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param dataSpec Defines the data to be cached.
* @param cache A {@link Cache} to store the data.
* @param cacheKeyFactory An optional factory for cache keys.
@ -159,6 +165,7 @@ public final class CacheUtil {
* @throws IOException If an error occurs reading from the source.
* @throws InterruptedException If the thread was interrupted directly or via {@code isCanceled}.
*/
@WorkerThread
public static void cache(
DataSpec dataSpec,
Cache cache,
@ -333,10 +340,13 @@ public final class CacheUtil {
/**
* Removes all of the data specified by the {@code dataSpec}.
*
* <p>This methods blocks until the operation is complete.
*
* @param dataSpec Defines the data to be removed.
* @param cache A {@link Cache} to store the data.
* @param cacheKeyFactory An optional factory for cache keys.
*/
@WorkerThread
public static void remove(
DataSpec dataSpec, Cache cache, @Nullable CacheKeyFactory cacheKeyFactory) {
remove(cache, buildCacheKey(dataSpec, cacheKeyFactory));
@ -345,9 +355,12 @@ public final class CacheUtil {
/**
* Removes all of the data specified by the {@code key}.
*
* <p>This methods blocks until the operation is complete.
*
* @param cache A {@link Cache} to store the data.
* @param key The key whose data should be removed.
*/
@WorkerThread
public static void remove(Cache cache, String key) {
NavigableSet<CacheSpan> cachedSpans = cache.getCachedSpans(key);
for (CacheSpan cachedSpan : cachedSpans) {

View File

@ -25,6 +25,7 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.database.DatabaseIOException;
import com.google.android.exoplayer2.database.DatabaseProvider;
import com.google.android.exoplayer2.database.VersionTable;
@ -104,10 +105,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* Deletes index data for the specified cache.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param databaseProvider Provides the database in which the index is stored.
* @param uid The cache UID.
* @throws DatabaseIOException If an error occurs deleting the index data.
*/
@WorkerThread
public static void delete(DatabaseProvider databaseProvider, long uid)
throws DatabaseIOException {
DatabaseStorage.delete(databaseProvider, uid);
@ -174,9 +178,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* Loads the index data for the given cache UID.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param uid The UID of the cache whose index is to be loaded.
* @throws IOException If an error occurs initializing the index data.
*/
@WorkerThread
public void initialize(long uid) throws IOException {
storage.initialize(uid);
if (previousStorage != null) {
@ -199,8 +206,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* Stores the index data to index file if there is a change.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @throws IOException If an error occurs storing the index data.
*/
@WorkerThread
public void store() throws IOException {
storage.storeIncremental(keyToContent);
// Make ids that were removed since the index was last stored eligible for re-use.

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream.cache;
import android.os.ConditionVariable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.database.DatabaseIOException;
import com.google.android.exoplayer2.database.DatabaseProvider;
@ -85,10 +86,13 @@ public final class SimpleCache implements Cache {
/**
* Deletes all content belonging to a cache instance.
*
* <p>This method may be slow and shouldn't normally be called on the main thread.
*
* @param cacheDir The cache directory.
* @param databaseProvider The database in which index data is stored, or {@code null} if the
* cache used a legacy index.
*/
@WorkerThread
public static void delete(File cacheDir, @Nullable DatabaseProvider databaseProvider) {
if (!cacheDir.exists()) {
return;
@ -147,6 +151,7 @@ public final class SimpleCache implements Cache {
* @deprecated Use a constructor that takes a {@link DatabaseProvider} for improved performance.
*/
@Deprecated
@SuppressWarnings("deprecation")
public SimpleCache(File cacheDir, CacheEvictor evictor, @Nullable byte[] secretKey) {
this(cacheDir, evictor, secretKey, secretKey != null);
}