data: work: Add required doc-comments for all workers
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -18,6 +18,9 @@ import java.util.concurrent.TimeUnit.MINUTES
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
/**
|
||||
* A periodic worker to automatically clear the old downloads cache periodically.
|
||||
*/
|
||||
@HiltWorker
|
||||
class CacheWorker @AssistedInject constructor(
|
||||
@Assisted private val appContext: Context,
|
||||
@@ -28,6 +31,11 @@ class CacheWorker @AssistedInject constructor(
|
||||
private const val TAG = "CleanCacheWorker"
|
||||
private const val CLEAN_CACHE_WORKER = "CLEAN_CACHE_WORKER"
|
||||
|
||||
/**
|
||||
* Schedules the automated cache cleanup
|
||||
* @param context Current [Context]
|
||||
* @see [CacheWorker]
|
||||
*/
|
||||
fun scheduleAutomatedCacheCleanup(context: Context) {
|
||||
val periodicWorkRequest = PeriodicWorkRequestBuilder<CacheWorker>(
|
||||
repeatInterval = 1,
|
||||
@@ -42,6 +50,9 @@ class CacheWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Duration to cache files, defaults to 6 hours
|
||||
*/
|
||||
private val cacheDuration = 6.toDuration(DurationUnit.HOURS)
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
@@ -73,6 +84,9 @@ class CacheWorker @AssistedInject constructor(
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the file if it's older than $[cacheDuration]
|
||||
*/
|
||||
private fun File.deleteIfOld() {
|
||||
val elapsedTime = Calendar.getInstance().timeInMillis - this.lastModified()
|
||||
if (elapsedTime.toDuration(DurationUnit.HOURS) > cacheDuration) {
|
||||
|
||||
@@ -56,6 +56,11 @@ import javax.net.ssl.HttpsURLConnection
|
||||
import kotlin.properties.Delegates
|
||||
import com.aurora.gplayapi.data.models.File as GPlayFile
|
||||
|
||||
/**
|
||||
* An expedited long-running worker to download and trigger installation for given apps.
|
||||
*
|
||||
* Avoid using this worker directly and prefer using [DownloadWorkerUtil] instead.
|
||||
*/
|
||||
@HiltWorker
|
||||
class DownloadWorker @AssistedInject constructor(
|
||||
private val downloadDao: DownloadDao,
|
||||
@@ -202,6 +207,13 @@ class DownloadWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Purchases the app to get the download URL of the required files
|
||||
* @param packageName The packageName of the app
|
||||
* @param versionCode Required version of the app
|
||||
* @param offerType Offer type of the app (free/paid)
|
||||
* @return A list of purchased files
|
||||
*/
|
||||
private fun purchase(packageName: String, versionCode: Int, offerType: Int): List<GPlayFile> {
|
||||
// Android 9.0+ supports key rotation, so purchase with latest certificate's hash
|
||||
return if (isPAndAbove() && download.isInstalled) {
|
||||
@@ -235,6 +247,12 @@ class DownloadWorker @AssistedInject constructor(
|
||||
return downloadList
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the file from the given request.
|
||||
* Failed downloads aren't removed and persists as long as [CacheWorker] doesn't cleans them.
|
||||
* @param request A [Request] to download
|
||||
* @return A [Result] indicating whether the file was downloaded or not.
|
||||
*/
|
||||
private suspend fun downloadFile(request: Request): Result {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val algorithm = if (request.sha256.isBlank()) Algorithm.SHA1 else Algorithm.SHA256
|
||||
@@ -278,6 +296,10 @@ class DownloadWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the progress data of the download in the local database and notifies user.
|
||||
* @param downloadInfo An instance of [DownloadInfo]
|
||||
*/
|
||||
private suspend fun onProgress(downloadInfo: DownloadInfo) {
|
||||
if (!isStopped && !download.isFinished) {
|
||||
downloadedBytes += downloadInfo.bytesCopied
|
||||
@@ -325,6 +347,11 @@ class DownloadWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the user of the current status of the download.
|
||||
* @param status Current [DownloadStatus]
|
||||
* @param dID ID of the notification, defaults to hashCode of the download's packageName
|
||||
*/
|
||||
private suspend fun notifyStatus(status: DownloadStatus, dID: Int = -1) {
|
||||
// Update status in database
|
||||
download.downloadStatus = status
|
||||
@@ -346,6 +373,13 @@ class DownloadWorker @AssistedInject constructor(
|
||||
notificationManager.notify(notificationID, notification)
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether given file has the expected SHA hash sum.
|
||||
* @param file [File] to check
|
||||
* @param expectedSha Expected SHA hash sum
|
||||
* @param algorithm [Algorithm] of the SHA
|
||||
* @return A boolean whether the given file has the expected SHA or not.
|
||||
*/
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private suspend fun validSha(file: File, expectedSha: String, algorithm: Algorithm): Boolean {
|
||||
return withContext(Dispatchers.IO) {
|
||||
@@ -362,6 +396,10 @@ class DownloadWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current [Proxy] configuration.
|
||||
* @return An instance of [Proxy] if configured by the user, null otherwise
|
||||
*/
|
||||
private fun getProxy(): Proxy? {
|
||||
val proxyEnabled = Preferences.getBoolean(appContext, PREFERENCE_PROXY_ENABLED)
|
||||
val proxyInfoString = Preferences.getString(appContext, PREFERENCE_PROXY_INFO)
|
||||
|
||||
@@ -35,6 +35,11 @@ import kotlinx.coroutines.withContext
|
||||
import java.util.concurrent.TimeUnit.HOURS
|
||||
import java.util.concurrent.TimeUnit.MINUTES
|
||||
|
||||
/**
|
||||
* A periodic worker to check for updates for installed apps based on
|
||||
* filters and the auto-updates mode selected by the user. The repeat interval
|
||||
* is configurable by the user, defaulting to 3 hours with a flex time of 30 minutes.
|
||||
*/
|
||||
@HiltWorker
|
||||
class UpdateWorker @AssistedInject constructor(
|
||||
private val downloadWorkerUtil: DownloadWorkerUtil,
|
||||
@@ -48,17 +53,32 @@ class UpdateWorker @AssistedInject constructor(
|
||||
private const val TAG = "UpdateWorker"
|
||||
private const val UPDATE_WORKER = "UPDATE_WORKER"
|
||||
|
||||
/**
|
||||
* Cancels the automated updates check
|
||||
* @param context Current [Context]
|
||||
* @see [UpdateWorker]
|
||||
*/
|
||||
fun cancelAutomatedCheck(context: Context) {
|
||||
Log.i(TAG, "Cancelling periodic app updates!")
|
||||
WorkManager.getInstance(context).cancelUniqueWork(UPDATE_WORKER)
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the automated updates check
|
||||
* @param context Current [Context]
|
||||
* @see [UpdateWorker]
|
||||
*/
|
||||
fun scheduleAutomatedCheck(context: Context) {
|
||||
Log.i(TAG,"Scheduling periodic app updates!")
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniquePeriodicWork(UPDATE_WORKER, KEEP, buildUpdateWork(context))
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the automated updates check to reconsider the new user preferences
|
||||
* @param context Current [Context]
|
||||
* @see [UpdateWorker]
|
||||
*/
|
||||
fun updateAutomatedCheck(context: Context) {
|
||||
Log.i(TAG,"Updating periodic app updates!")
|
||||
WorkManager.getInstance(context).updateWork(buildUpdateWork(context))
|
||||
@@ -165,6 +185,9 @@ class UpdateWorker @AssistedInject constructor(
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given package can be auto-updated or not
|
||||
*/
|
||||
private fun canAutoUpdate(packageName: String): Boolean {
|
||||
return when (AppInstaller.getCurrentInstaller(appContext)) {
|
||||
Installer.SESSION -> isSAndAbove() && CertUtil.isAuroraStoreApp(appContext, packageName)
|
||||
|
||||
@@ -23,6 +23,9 @@ import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Helper class to work with the [DownloadWorker].
|
||||
*/
|
||||
class DownloadWorkerUtil @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val downloadDao: DownloadDao,
|
||||
@@ -44,6 +47,9 @@ class DownloadWorkerUtil @Inject constructor(
|
||||
|
||||
private val TAG = DownloadWorkerUtil::class.java.simpleName
|
||||
|
||||
/**
|
||||
* Removes failed download from the queue and starts observing for newly enqueued apps.
|
||||
*/
|
||||
fun init() {
|
||||
AuroraApp.scope.launch {
|
||||
cancelFailedDownloads(downloadDao.downloads().firstOrNull() ?: emptyList())
|
||||
@@ -72,10 +78,18 @@ class DownloadWorkerUtil @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues an app for download & install
|
||||
* @param app [App] to download
|
||||
*/
|
||||
suspend fun enqueueApp(app: App) {
|
||||
downloadDao.insert(Download.fromApp(app))
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the download for the given package
|
||||
* @param packageName Name of the package to cancel download
|
||||
*/
|
||||
suspend fun cancelDownload(packageName: String) {
|
||||
Log.i(TAG, "Cancelling download for $packageName")
|
||||
WorkManager.getInstance(context).cancelAllWorkByTag("$PACKAGE_NAME:$packageName")
|
||||
@@ -84,6 +98,11 @@ class DownloadWorkerUtil @Inject constructor(
|
||||
?.let { downloadDao.updateStatus(packageName, DownloadStatus.CANCELLED) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the entry & downloaded files for the given package
|
||||
* @param packageName Name of the package of the app
|
||||
* @param versionCode Version of the package
|
||||
*/
|
||||
suspend fun clearDownload(packageName: String, versionCode: Int) {
|
||||
Log.i(TAG, "Clearing downloads for $packageName ($versionCode)")
|
||||
downloadDao.delete(packageName)
|
||||
@@ -91,6 +110,9 @@ class DownloadWorkerUtil @Inject constructor(
|
||||
.deleteRecursively()
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the downloads and their downloaded files
|
||||
*/
|
||||
suspend fun clearAllDownloads() {
|
||||
Log.i(TAG, "Clearing all downloads!")
|
||||
downloadDao.deleteAll()
|
||||
@@ -98,12 +120,19 @@ class DownloadWorkerUtil @Inject constructor(
|
||||
PathUtil.getOldDownloadDirectories(context).forEach { it.deleteRecursively() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears finished downloads and their downloaded files
|
||||
*/
|
||||
suspend fun clearFinishedDownloads() {
|
||||
downloadsList.value.filter { it.isFinished }.forEach {
|
||||
clearDownload(it.packageName, it.versionCode)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels all the ongoing and queued downloads
|
||||
* @param updatesOnly Whether to cancel only updates, defaults to false
|
||||
*/
|
||||
suspend fun cancelAll(updatesOnly: Boolean = false) {
|
||||
// Cancel all enqueued downloads first to avoid triggering re-download
|
||||
downloadsList.value.filter { it.downloadStatus == DownloadStatus.QUEUED }
|
||||
|
||||
Reference in New Issue
Block a user