Remove WorkManager as a dependency

This commit is contained in:
topjohnwu 2021-11-04 23:39:35 -07:00
parent fca5eb083f
commit 81f57949ed
13 changed files with 96 additions and 178 deletions

View File

@ -123,12 +123,11 @@ dependencies {
implementation("androidx.biometric:biometric:1.1.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.browser:browser:1.3.0")
implementation("androidx.browser:browser:1.4.0")
implementation("androidx.preference:preference:1.1.1")
implementation("androidx.recyclerview:recyclerview:1.2.1")
implementation("androidx.fragment:fragment-ktx:1.3.6")
implementation("androidx.work:work-runtime-ktx:2.7.0")
implementation("androidx.transition:transition:1.4.1")
implementation("androidx.core:core-ktx:1.6.0")
implementation("androidx.core:core-ktx:1.7.0")
implementation("com.google.android.material:material:1.4.0")
}

View File

@ -12,7 +12,6 @@
android:multiArch="true"
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
<!-- Splash -->
<activity
android:name=".core.SplashActivity"
android:exported="true"
@ -27,10 +26,10 @@
</intent-filter>
</activity>
<!-- Main -->
<activity android:name=".ui.MainActivity" />
<activity
android:name=".ui.MainActivity"
android:exported="false" />
<!-- Superuser -->
<activity
android:name=".ui.surequest.SuRequestActivity"
android:directBootAware="true"
@ -43,7 +42,6 @@
</intent-filter>
</activity>
<!-- Receiver -->
<receiver
android:name=".core.Receiver"
android:directBootAware="true"
@ -60,10 +58,15 @@
</intent-filter>
</receiver>
<!-- DownloadService -->
<service android:name=".core.download.DownloadService" />
<service
android:name=".core.download.DownloadService"
android:exported="false" />
<service
android:name=".core.JobService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- FileProvider -->
<provider
android:name=".core.Provider"
android:authorities="${applicationId}.provider"
@ -71,13 +74,6 @@
android:exported="false"
android:grantUriPermissions="true" />
<!-- Initialize WorkManager on-demand -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove">
</provider>
<!-- We don't invalidate Room -->
<service
android:name="androidx.room.MultiInstanceInvalidationService"

View File

@ -7,7 +7,6 @@ import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate
import androidx.work.WorkManager
import com.topjohnwu.magisk.DynAPK
import com.topjohnwu.magisk.core.utils.AppShellInit
import com.topjohnwu.magisk.core.utils.BusyBoxInit
@ -58,7 +57,6 @@ open class App() : Application() {
ServiceLocator.context = wrapped
AssetHack.init(impl)
app.registerActivityLifecycleCallbacks(ForegroundTracker)
WorkManager.initialize(impl.wrapJob(), androidx.work.Configuration.Builder().build())
}
// This is required as some platforms expect ContextImpl

View File

@ -41,9 +41,9 @@ object Const {
object ID {
// notifications
const val APK_UPDATE_NOTIFICATION_ID = 5
const val JOB_SERVICE_ID = 7
const val UPDATE_NOTIFICATION_CHANNEL = "update"
const val PROGRESS_NOTIFICATION_CHANNEL = "progress"
const val CHECK_MAGISK_UPDATE_WORKER_ID = "magisk_update"
}
object Url {

View File

@ -2,11 +2,7 @@
package com.topjohnwu.magisk.core
import android.annotation.SuppressLint
import android.app.Activity
import android.app.job.JobInfo
import android.app.job.JobScheduler
import android.app.job.JobWorkItem
import android.content.ComponentName
import android.content.Context
import android.content.ContextWrapper
@ -15,7 +11,6 @@ import android.content.res.AssetManager
import android.content.res.Configuration
import android.content.res.Resources
import android.util.DisplayMetrics
import androidx.annotation.RequiresApi
import com.topjohnwu.magisk.DynAPK
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.utils.refreshLocale
@ -28,22 +23,6 @@ fun AssetManager.addAssetPath(path: String) {
fun Context.wrap(inject: Boolean = false): Context =
if (inject) ReInjectedContext(this) else InjectedContext(this)
fun Context.wrapJob(): Context = object : InjectedContext(this) {
override fun getApplicationContext() = this
@SuppressLint("NewApi")
override fun getSystemService(name: String): Any? {
return super.getSystemService(name).let {
when {
!isRunningAsStub -> it
name == JOB_SCHEDULER_SERVICE -> JobSchedulerWrapper(it as JobScheduler)
else -> it
}
}
}
}
fun Class<*>.cmp(pkg: String) =
ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name)
@ -99,28 +78,6 @@ object AssetHack {
}
}
@RequiresApi(28)
private class JobSchedulerWrapper(private val base: JobScheduler) : JobScheduler() {
override fun schedule(job: JobInfo) = base.schedule(job.patch())
override fun enqueue(job: JobInfo, work: JobWorkItem) = base.enqueue(job.patch(), work)
override fun cancel(jobId: Int) = base.cancel(jobId)
override fun cancelAll() = base.cancelAll()
override fun getAllPendingJobs(): List<JobInfo> = base.allPendingJobs
override fun getPendingJob(jobId: Int) = base.getPendingJob(jobId)
private fun JobInfo.patch(): JobInfo {
// Swap out the service of JobInfo
val component = service.run {
ComponentName(packageName,
Info.stub?.classToComponent?.get(className) ?: className)
}
javaClass.getDeclaredField("service").apply {
isAccessible = true
}.set(this, component)
return this
}
}
// Keep a reference to these resources to prevent it from
// being removed when running "remove unused resources"
val shouldKeepResources = listOf(

View File

@ -0,0 +1,56 @@
package com.topjohnwu.magisk.core
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.content.Context
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.core.base.BaseJobService
import com.topjohnwu.magisk.di.ServiceLocator
import com.topjohnwu.magisk.view.Notifications
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit
class JobService : BaseJobService() {
private val job = Job()
private val svc get() = ServiceLocator.networkService
override fun onStartJob(params: JobParameters): Boolean {
val coroutineScope = CoroutineScope(Dispatchers.IO + job)
coroutineScope.launch {
svc.fetchUpdate()?.run {
if (Info.env.isActive && BuildConfig.VERSION_CODE < magisk.versionCode)
Notifications.managerUpdate(this@JobService)
}
jobFinished(params, false)
}
return false
}
override fun onStopJob(params: JobParameters): Boolean {
job.cancel()
return false
}
companion object {
fun schedule(context: Context) {
val svc = context.getSystemService<JobScheduler>() ?: return
if (Config.checkUpdate) {
val cmp = JobService::class.java.cmp(context.packageName)
val info = JobInfo.Builder(Const.ID.JOB_SERVICE_ID, cmp)
.setPeriodic(TimeUnit.HOURS.toMillis(12))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setRequiresDeviceIdle(true)
.build()
svc.schedule(info)
} else {
svc.cancel(Const.ID.JOB_SERVICE_ID)
}
}
}
}

View File

@ -15,7 +15,7 @@ import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
import java.util.concurrent.CountDownLatch
open class SplashActivity : BaseActivity() {
class SplashActivity : BaseActivity() {
private val latch = CountDownLatch(1)
@ -63,7 +63,7 @@ open class SplashActivity : BaseActivity() {
Config.load(prevPkg)
handleRepackage(prevPkg)
Notifications.setup(this)
UpdateCheckService.schedule(this)
JobService.schedule(this)
Shortcuts.setupDynamic(this)
// Pre-fetch network services

View File

@ -1,44 +0,0 @@
package com.topjohnwu.magisk.core
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.*
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.di.ServiceLocator
import com.topjohnwu.magisk.view.Notifications
import java.util.concurrent.TimeUnit
class UpdateCheckService(context: Context, workerParams: WorkerParameters)
: CoroutineWorker(context, workerParams) {
private val svc get() = ServiceLocator.networkService
override suspend fun doWork(): Result {
return svc.fetchUpdate()?.run {
if (Info.env.isActive && BuildConfig.VERSION_CODE < magisk.versionCode)
Notifications.managerUpdate(applicationContext)
Result.success()
} ?: Result.failure()
}
companion object {
@SuppressLint("NewApi")
fun schedule(context: Context) {
if (Config.checkUpdate) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresDeviceIdle(true)
.build()
val request = PeriodicWorkRequestBuilder<UpdateCheckService>(12, TimeUnit.HOURS)
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID,
ExistingPeriodicWorkPolicy.REPLACE, request)
} else {
WorkManager.getInstance(context)
.cancelUniqueWork(Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID)
}
}
}
}

View File

@ -0,0 +1,11 @@
package com.topjohnwu.magisk.core.base
import android.app.job.JobService
import android.content.Context
import com.topjohnwu.magisk.core.wrap
abstract class BaseJobService : JobService() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base.wrap())
}
}

View File

@ -1,59 +0,0 @@
package com.topjohnwu.magisk.core.base
import android.content.Context
import android.net.Network
import android.net.Uri
import androidx.annotation.MainThread
import androidx.annotation.RequiresApi
import androidx.work.Data
import androidx.work.ListenableWorker
import com.google.common.util.concurrent.ListenableFuture
import java.util.*
abstract class BaseWorkerWrapper {
private lateinit var worker: ListenableWorker
val applicationContext: Context
get() = worker.applicationContext
val id: UUID
get() = worker.id
val inputData: Data
get() = worker.inputData
val tags: Set<String>
get() = worker.tags
val triggeredContentUris: List<Uri>
@RequiresApi(24)
get() = worker.triggeredContentUris
val triggeredContentAuthorities: List<String>
@RequiresApi(24)
get() = worker.triggeredContentAuthorities
val network: Network?
@RequiresApi(28)
get() = worker.network
val runAttemptCount: Int
get() = worker.runAttemptCount
val isStopped: Boolean
get() = worker.isStopped
abstract fun doWork(): ListenableWorker.Result
fun onStopped() {}
fun attachWorker(w: ListenableWorker) {
worker = w
}
@MainThread
fun startWork(): ListenableFuture<ListenableWorker.Result> {
return worker.startWork()
}
}

View File

@ -12,7 +12,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.UpdateCheckService
import com.topjohnwu.magisk.core.JobService
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
@ -185,7 +185,7 @@ object UpdateChecker : BaseSettingsItem.Toggle() {
override var value = Config.checkUpdate
set(value) = setV(value, field, { field = it }) {
Config.checkUpdate = it
UpdateCheckService.schedule(AppContext)
JobService.schedule(AppContext)
}
}

View File

@ -153,7 +153,10 @@ fun genStubManifest(srcDir: File, outDir: File): String {
cmpList.add(Component(
"com.topjohnwu.magisk.ui.MainActivity",
"",
"""|<activity android:name="%s" />""".ind(2)
"""
|<activity
| android:name="%s"
| android:exported="false" />""".ind(2)
))
cmpList.add(Component(
@ -176,18 +179,19 @@ fun genStubManifest(srcDir: File, outDir: File): String {
cmpList.add(Component(
"com.topjohnwu.magisk.core.download.DownloadService",
"",
"""|<service android:name="%s" />""".ind(2)
"""
|<service
| android:name="%s"
| android:exported="false" />""".trimIndent().ind(2)
))
cmpList.add(Component(
"androidx.work.impl.background.systemjob.SystemJobService",
"com.topjohnwu.magisk.core.JobService",
"",
"""
|<service
| android:name="%s"
| android:directBootAware="false"
| android:enabled="true"
| android:exported="true"
| android:exported="false"
| android:permission="android.permission.BIND_JOB_SERVICE" />""".ind(2)
))

View File

@ -30,7 +30,7 @@ android.injected.testOnly=false
kapt.incremental.apt=true
# Magisk
magisk.stubVersion=21
magisk.stubVersion=22
magisk.versionCode=23012
magisk.ndkVersion=21e
magisk.fullNdkVersion=21.4.7075529