From 676e9c659372f3a9f86de3384ecfef7b62926c62 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 24 Oct 2019 02:47:40 -0400 Subject: [PATCH] Provide upgrade path for stubs --- .../magisk/model/download/DownloadService.kt | 13 +---- .../magisk/model/download/ManagerUpgrade.kt | 52 +++++++++++++------ .../model/download/RemoteFileService.kt | 2 +- .../com/topjohnwu/magisk/utils/PatchAPK.kt | 8 ++- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/model/download/DownloadService.kt b/app/src/main/java/com/topjohnwu/magisk/model/download/DownloadService.kt index 082978af0..3f0eca392 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/download/DownloadService.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/download/DownloadService.kt @@ -7,20 +7,17 @@ import android.content.Intent import android.os.Build import android.webkit.MimeTypeMap import androidx.core.app.NotificationCompat -import com.topjohnwu.magisk.ProcessPhoenix import com.topjohnwu.magisk.R import com.topjohnwu.magisk.extensions.chooser import com.topjohnwu.magisk.extensions.exists import com.topjohnwu.magisk.extensions.provide import com.topjohnwu.magisk.intent -import com.topjohnwu.magisk.isRunningAsStub import com.topjohnwu.magisk.model.entity.internal.Configuration.* import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.* import com.topjohnwu.magisk.ui.flash.FlashActivity import com.topjohnwu.magisk.utils.APKInstall -import com.topjohnwu.magisk.utils.DynAPK import org.koin.core.get import java.io.File import kotlin.random.Random.Default.nextInt @@ -65,15 +62,7 @@ open class DownloadService : RemoteFileService() { ) { remove(id) when (subject.configuration) { - is APK.Upgrade -> { - if (isRunningAsStub) { - subject.file.copyTo(DynAPK.update(this), overwrite = true) - subject.file.delete() - ProcessPhoenix.triggerRebirth(this) - } else { - APKInstall.install(this, subject.file) - } - } + is APK.Upgrade -> APKInstall.install(this, subject.file) is APK.Restore -> Unit } } diff --git a/app/src/main/java/com/topjohnwu/magisk/model/download/ManagerUpgrade.kt b/app/src/main/java/com/topjohnwu/magisk/model/download/ManagerUpgrade.kt index 18cb448a7..3f5d98976 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/download/ManagerUpgrade.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/download/ManagerUpgrade.kt @@ -1,28 +1,48 @@ package com.topjohnwu.magisk.model.download -import com.topjohnwu.magisk.BuildConfig -import com.topjohnwu.magisk.Config -import com.topjohnwu.magisk.R -import com.topjohnwu.magisk.isRunningAsStub +import com.topjohnwu.magisk.* +import com.topjohnwu.magisk.extensions.writeTo import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade import com.topjohnwu.magisk.model.entity.internal.DownloadSubject +import com.topjohnwu.magisk.utils.DynAPK import com.topjohnwu.magisk.utils.PatchAPK import com.topjohnwu.superuser.Shell import java.io.File -private fun RemoteFileService.patchPackage(apk: File, id: Int) { - if (!isRunningAsStub && packageName != BuildConfig.APPLICATION_ID) { - update(id) { notification -> - notification.setProgress(0, 0, true) - .setProgress(0, 0, true) - .setContentTitle(getString(R.string.hide_manager_title)) - .setContentText("") - } - val patched = File(apk.parent, "patched.apk") - PatchAPK.patch(apk, patched, packageName, applicationInfo.nonLocalizedLabel.toString()) +private fun RemoteFileService.patch(apk: File, id: Int) { + if (packageName == BuildConfig.APPLICATION_ID) + return + + update(id) { notification -> + notification.setProgress(0, 0, true) + .setProgress(0, 0, true) + .setContentTitle(getString(R.string.hide_manager_title)) + .setContentText("") + } + val patched = File(apk.parent, "patched.apk") + PatchAPK.patch(apk, patched, packageName, applicationInfo.nonLocalizedLabel.toString()) + apk.delete() + patched.renameTo(apk) +} + +private fun RemoteFileService.upgrade(apk: File, id: Int) { + if (isRunningAsStub) { + // Move to upgrade location + apk.copyTo(DynAPK.update(this), overwrite = true) apk.delete() - patched.renameTo(apk) + if (ClassMap.data!!.version < Info.remote.stub.versionCode) { + // We also want to upgrade stub + service.fetchFile(Info.remote.stub.link).blockingGet().byteStream().use { + it.writeTo(apk) + } + patch(apk, id) + } else { + // Simply relaunch the app + ProcessPhoenix.triggerRebirth(this) + } + } else { + patch(apk, id) } } @@ -41,6 +61,6 @@ private fun RemoteFileService.restore(apk: File, id: Int) { fun RemoteFileService.handleAPK(subject: DownloadSubject.Manager) = when (subject.configuration) { - is Upgrade -> patchPackage(subject.file, subject.hashCode()) + is Upgrade -> upgrade(subject.file, subject.hashCode()) is Restore -> restore(subject.file, subject.hashCode()) } diff --git a/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt b/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt index febd7fb2f..418a4d3de 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt @@ -22,7 +22,7 @@ import java.io.InputStream abstract class RemoteFileService : NotificationService() { - private val service: GithubRawServices by inject() + val service: GithubRawServices by inject() override val defaultNotification: NotificationCompat.Builder get() = Notifications.progress(this, "") diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.kt b/app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.kt index 2d8d3b356..3c82b4642 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.kt @@ -138,6 +138,11 @@ object PatchAPK { fun patch(apk: File, out: File, pkg: String, label: String): Boolean { try { + if (apk.length() < 1 shl 18) { + // APK is smaller than 256K, must be stub + return patch(apk.path, out.path, pkg, label) + } + // Try using the new APK to patch itself val loader = DynamicClassLoader(apk) val cls = loader.loadClass("a.a") @@ -152,9 +157,8 @@ object PatchAPK { } catch (e: Exception) { Timber.e(e) // Fallback to use the current implementation - patch(apk.path, out.path, pkg, label) + return patch(apk.path, out.path, pkg, label) } - return false } fun hideManager(context: Context, label: String) {