Make stub patching 100% offline

This commit is contained in:
topjohnwu 2022-08-26 03:43:31 -07:00
parent cdc66c1ac8
commit 71b0c8b42b
4 changed files with 29 additions and 21 deletions

View File

@ -31,6 +31,7 @@ import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
@ -44,14 +45,12 @@ class DownloadService : NotificationService() {
} }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy()
job.cancel() job.cancel()
} }
private fun download(subject: Subject) { private fun download(subject: Subject) {
notifyUpdate(subject.notifyId) notifyUpdate(subject.notifyId)
val coroutineScope = CoroutineScope(job + Dispatchers.IO) CoroutineScope(job + Dispatchers.IO).launch {
coroutineScope.launch {
try { try {
val stream = service.fetchFile(subject.url).toProgressStream(subject) val stream = service.fetchFile(subject.url).toProgressStream(subject)
when (subject) { when (subject) {
@ -75,7 +74,7 @@ class DownloadService : NotificationService() {
} }
} }
private suspend fun handleApp(stream: InputStream, subject: Subject.App) { private fun handleApp(stream: InputStream, subject: Subject.App) {
fun writeTee(output: OutputStream) { fun writeTee(output: OutputStream) {
val uri = MediaStoreUtils.getFile("${subject.title}.apk").uri val uri = MediaStoreUtils.getFile("${subject.title}.apk").uri
val external = uri.outputStream() val external = uri.outputStream()
@ -96,9 +95,10 @@ class DownloadService : NotificationService() {
.setContentText("") .setContentText("")
} }
// Download // Extract stub
val apk = subject.file.toFile() val apk = subject.file.toFile()
service.fetchFile(subject.stub.link).byteStream().writeTo(apk) val zf = ZipFile(updateApk)
zf.getInputStream(zf.getEntry("assets/stub.apk")).writeTo(apk)
// Patch and install // Patch and install
val session = APKInstall.startSession(this) val session = APKInstall.startSession(this)

View File

@ -22,8 +22,7 @@ data class MagiskJson(
@Parcelize @Parcelize
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class StubJson( data class StubJson(
val versionCode: Int = -1, val versionCode: Int = -1
val link: String = ""
) : Parcelable ) : Parcelable
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)

View File

@ -9,9 +9,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.Provider import com.topjohnwu.magisk.core.Provider
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.utils.AXML import com.topjohnwu.magisk.core.utils.AXML
import com.topjohnwu.magisk.core.utils.Keygen import com.topjohnwu.magisk.core.utils.Keygen
import com.topjohnwu.magisk.ktx.await import com.topjohnwu.magisk.ktx.await
@ -40,8 +38,6 @@ object HideAPK {
// Some arbitrary limit // Some arbitrary limit
const val MAX_LABEL_LENGTH = 32 const val MAX_LABEL_LENGTH = 32
private val svc get() = ServiceLocator.networkService
private fun genPackageName(): String { private fun genPackageName(): String {
val random = SecureRandom() val random = SecureRandom()
val len = 5 + random.nextInt(15) val len = 5 + random.nextInt(15)
@ -113,16 +109,12 @@ object HideAPK {
activity.finish() activity.finish()
} }
@Suppress("BlockingMethodInNonBlockingContext") private fun patchAndHide(activity: Activity, label: String, onFailure: Runnable): Boolean {
private suspend fun patchAndHide(activity: Activity, label: String, onFailure: Runnable): Boolean {
val stub = File(activity.cacheDir, "stub.apk") val stub = File(activity.cacheDir, "stub.apk")
try { try {
svc.fetchFile(Info.remote.stub.link).byteStream().writeTo(stub) activity.assets.open("stub.apk").writeTo(stub)
} catch (e: IOException) { } catch (e: IOException) {
Timber.e(e) Timber.e(e)
stub.createNewFile()
val cmd = "\$MAGISKBIN/magiskinit -x manager ${stub.path}"
if (!Shell.cmd(cmd).exec().isSuccess)
return false return false
} }

View File

@ -11,6 +11,7 @@ import org.gradle.api.Action
import org.gradle.api.JavaVersion import org.gradle.api.JavaVersion
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Delete import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.StopExecutionException import org.gradle.api.tasks.StopExecutionException
import org.gradle.api.tasks.Sync import org.gradle.api.tasks.Sync
@ -218,13 +219,29 @@ fun Project.setupApp() {
} }
android.applicationVariants.all { android.applicationVariants.all {
preBuildProvider.get().dependsOn(syncResources) val variantCapped = name.capitalize(Locale.ROOT)
val variantLowered = name.toLowerCase(Locale.ROOT)
val copyStub = tasks.register("copy${variantCapped}StubApk", Copy::class.java) {
dependsOn(syncResources)
into("src/main/assets")
from(rootProject.file("out/stub-${variantLowered}.apk")) {
rename { "stub.apk" }
}
onlyIf {
if (inputs.sourceFiles.files.size != 1)
throw StopExecutionException("Please build stub first! (./build.py stub)")
true
}
}
preBuildProvider.get().dependsOn(copyStub)
val keysDir = rootProject.file("tools/keys") val keysDir = rootProject.file("tools/keys")
val outSrcDir = File(buildDir, "generated/source/keydata/$name") val outSrcDir = File(buildDir, "generated/source/keydata/$name")
val outSrc = File(outSrcDir, "com/topjohnwu/magisk/signing/KeyData.java") val outSrc = File(outSrcDir, "com/topjohnwu/magisk/signing/KeyData.java")
val genSrcTask = tasks.register("generate${name.capitalize(Locale.ROOT)}KeyData") { val genSrcTask = tasks.register("generate${variantCapped}KeyData") {
inputs.dir(keysDir) inputs.dir(keysDir)
outputs.file(outSrc) outputs.file(outSrc)
doLast { doLast {