diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt index 7cb3507586d7..793e43d81a9f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt @@ -20,6 +20,7 @@ import android.widget.ProgressBar import androidx.activity.result.ActivityResultLauncher import androidx.annotation.LayoutRes import androidx.annotation.StringRes +import androidx.annotation.UiThread import androidx.appcompat.app.ActionBar import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate @@ -59,6 +60,7 @@ import com.ichi2.utils.KotlinCleanup import com.ichi2.utils.SyncStatus import timber.log.Timber +@UiThread open class AnkiActivity : AppCompatActivity, SimpleMessageDialogListener, CollectionGetter { /** The name of the parent class (example: 'Reviewer') */ diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt index e9af16e973da..e2bed11f0328 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt @@ -18,6 +18,7 @@ package com.ichi2.anki import android.annotation.SuppressLint import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import anki.backend.backendError import com.ichi2.libanki.Collection import com.ichi2.libanki.CollectionV16 @@ -78,7 +79,7 @@ object CollectionManager { * * context(Queue) suspend fun canOnlyBeRunInWithQueue() */ - private suspend fun withQueue(block: CollectionManager.() -> T): T { + private suspend fun withQueue(@WorkerThread block: CollectionManager.() -> T): T { return withContext(queue) { this@CollectionManager.block() } @@ -91,7 +92,7 @@ object CollectionManager { * sure the collection won't be closed or modified by another thread. This guarantee * does not hold if legacy code calls [getColUnsafe]. */ - suspend fun withCol(block: Collection.() -> T): T { + suspend fun withCol(@WorkerThread block: Collection.() -> T): T { return withQueue { ensureOpenInner() block(collection!!) @@ -105,7 +106,7 @@ object CollectionManager { * these two cases, it should wrap the return value of the block in a class (eg Optional), * instead of returning a nullable object. */ - suspend fun withOpenColOrNull(block: Collection.() -> T): T? { + suspend fun withOpenColOrNull(@WorkerThread block: Collection.() -> T): T? { return withQueue { if (collection != null && !collection!!.dbClosed) { block(collection!!) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt index 93691c942cde..e2b611afdc8d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt @@ -36,10 +36,7 @@ import android.view.View.OnFocusChangeListener import android.view.ViewGroup.MarginLayoutParams import android.widget.* import android.widget.AdapterView.OnItemSelectedListener -import androidx.annotation.CheckResult -import androidx.annotation.RequiresApi -import androidx.annotation.StringRes -import androidx.annotation.VisibleForTesting +import androidx.annotation.* import androidx.appcompat.app.AlertDialog import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.AppCompatButton diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt index 40aef3e15f80..0ca5d6675e48 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt @@ -28,6 +28,7 @@ import android.content.res.Resources import android.database.sqlite.SQLiteDatabaseLockedException import androidx.annotation.CheckResult import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import anki.search.SearchNode import anki.search.SearchNodeKt import anki.search.searchNode @@ -80,6 +81,7 @@ import kotlin.random.Random @KotlinCleanup("TextUtils -> Kotlin isNotEmpty()") @KotlinCleanup("inline function in init { } so we don't need to init `crt` etc... at the definition") @KotlinCleanup("ids.size != 0") +@WorkerThread open class Collection( /** * @return The context that created this Collection. diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/ConfigManager.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/ConfigManager.kt index 6f91ce42d9d1..3c6e71a9cb7c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/ConfigManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/ConfigManager.kt @@ -17,9 +17,11 @@ package com.ichi2.libanki import androidx.annotation.CheckResult +import androidx.annotation.WorkerThread import org.json.JSONArray import org.json.JSONObject +@WorkerThread abstract class ConfigManager { @CheckResult abstract fun has(key: String): Boolean diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/DB.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/DB.kt index ae94a4fe5465..d227116c7f44 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/DB.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/DB.kt @@ -24,6 +24,7 @@ import android.content.Context import android.database.Cursor import android.database.SQLException import android.database.sqlite.SQLiteDatabase +import androidx.annotation.WorkerThread import androidx.sqlite.db.SupportSQLiteDatabase import com.ichi2.anki.BuildConfig import com.ichi2.anki.CollectionHelper @@ -41,6 +42,7 @@ import timber.log.Timber * or the Android framework), and provides some helpers on top. */ @KotlinCleanup("Improve documentation") +@WorkerThread class DB(db: SupportSQLiteDatabase) { /** * The collection, which is actually an SQLite database. diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/DeckManager.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/DeckManager.kt index 3b5294adb816..284e1506434a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/DeckManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/DeckManager.kt @@ -18,6 +18,7 @@ package com.ichi2.libanki import androidx.annotation.CheckResult import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import com.ichi2.anki.exception.ConfirmModSchemaException import com.ichi2.libanki.backend.exception.DeckRenameException import com.ichi2.utils.DeckComparator @@ -27,6 +28,7 @@ import net.ankiweb.rsdroid.RustCleanup import org.intellij.lang.annotations.Language import java.util.* +@WorkerThread abstract class DeckManager { /* diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Decks.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Decks.kt index d7525a89550e..5235e4e82107 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Decks.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Decks.kt @@ -24,6 +24,7 @@ package com.ichi2.libanki import android.content.ContentValues import androidx.annotation.CheckResult import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import com.ichi2.anki.CrashReportService import com.ichi2.anki.exception.ConfirmModSchemaException import com.ichi2.libanki.Consts.DECK_STD @@ -47,6 +48,7 @@ import java.util.regex.Pattern @KotlinCleanup("remove unused functions") @KotlinCleanup("where ever possible replace ArrayList() with mutableListOf()") @KotlinCleanup("nullability") +@WorkerThread class Decks(private val col: Collection) : DeckManager() { @get:RustCleanup("This exists in Rust as DecksDictProxy, but its usage is warned against") @KotlinCleanup("lateinit") diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Media.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Media.kt index f6ab3cb5d733..efdeffe37d9e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Media.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Media.kt @@ -21,6 +21,7 @@ import android.database.Cursor import android.database.SQLException import android.net.Uri import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import com.ichi2.anki.CrashReportService import com.ichi2.libanki.exception.EmptyMediaException import com.ichi2.libanki.template.TemplateFilters @@ -58,6 +59,7 @@ import kotlin.math.min * E.g: new File(dir(), "filename.jpg") */ @KotlinCleanup("IDE Lint") +@WorkerThread open class Media(private val col: Collection, server: Boolean) { private var mDir: String? diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/ModelManager.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/ModelManager.kt index 2525c97c353a..f1ee01a10b69 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/ModelManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/ModelManager.kt @@ -16,6 +16,7 @@ package com.ichi2.libanki +import androidx.annotation.WorkerThread import com.ichi2.anki.CrashReportService import com.ichi2.anki.exception.ConfirmModSchemaException import com.ichi2.utils.Assert @@ -23,6 +24,7 @@ import net.ankiweb.rsdroid.RustCleanup import org.json.JSONObject import timber.log.Timber +@WorkerThread abstract class ModelManager(protected val col: Collection) { /* diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Tags.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Tags.kt index 350ea25a9e0c..f90a8c520459 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Tags.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Tags.kt @@ -18,6 +18,7 @@ package com.ichi2.libanki import android.content.ContentValues +import androidx.annotation.WorkerThread import com.ichi2.libanki.backend.model.TagUsnTuple import com.ichi2.libanki.utils.TimeManager import org.json.JSONObject @@ -35,6 +36,7 @@ import java.util.regex.Pattern * instead of a JSONObject. It is much more convenient to work with a TreeMap in Java, but there * may be a performance penalty in doing so (on startup and shutdown). */ +@WorkerThread class Tags /** * Registry save/load diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/sched/BaseSched.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/sched/BaseSched.kt index 15c87417d26b..a0b75796cd04 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/sched/BaseSched.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/sched/BaseSched.kt @@ -23,6 +23,7 @@ import android.graphics.Typeface import android.text.SpannableStringBuilder import android.text.style.StyleSpan import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import anki.ankidroid.schedTimingTodayLegacyRequest import anki.decks.DeckTreeNode import anki.scheduler.* @@ -45,6 +46,8 @@ import net.ankiweb.rsdroid.RustCleanup * BackendFactory.defaultLegacySchema is false, so for now, SchedV2 * will need to (conditionally) override them. */ + +@WorkerThread abstract class BaseSched(val col: Collection) { /** Update a V1 scheduler collection to V2. Requires full sync. */ fun upgradeToV2() { diff --git a/lint-release.xml b/lint-release.xml index d799ea2fa577..302269fca444 100644 --- a/lint-release.xml +++ b/lint-release.xml @@ -330,7 +330,7 @@ - +