mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 20:15:29 +00:00
Updated service to use extra transformer so the service itself is not plagued by unnecessary code
This commit is contained in:
parent
78282c1a49
commit
7cd814d917
@ -4,6 +4,8 @@ import android.content.Context
|
|||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.skoumal.teanity.rxbus.RxBus
|
import com.skoumal.teanity.rxbus.RxBus
|
||||||
import com.topjohnwu.magisk.App
|
import com.topjohnwu.magisk.App
|
||||||
|
import com.topjohnwu.magisk.model.download.ModuleTransformer
|
||||||
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
|
||||||
@ -15,4 +17,6 @@ val applicationModule = module {
|
|||||||
factory(Protected) { get<App>().protectedContext }
|
factory(Protected) { get<App>().protectedContext }
|
||||||
single(SUTimeout) { get<Context>(Protected).getSharedPreferences("su_timeout", 0) }
|
single(SUTimeout) { get<Context>(Protected).getSharedPreferences("su_timeout", 0) }
|
||||||
single { PreferenceManager.getDefaultSharedPreferences(get<Context>(Protected)) }
|
single { PreferenceManager.getDefaultSharedPreferences(get<Context>(Protected)) }
|
||||||
|
|
||||||
|
factory { (subject: DownloadSubject) -> ModuleTransformer(get(), subject) }
|
||||||
}
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.topjohnwu.magisk.model.download
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
|
import com.topjohnwu.magisk.utils.cachedFile
|
||||||
|
import com.topjohnwu.magisk.utils.withStreams
|
||||||
|
import java.io.File
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipInputStream
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
|
class ModuleTransformer(
|
||||||
|
private val context: Context,
|
||||||
|
subject: DownloadSubject
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val destination = context.cachedFile(subject.fileName)
|
||||||
|
|
||||||
|
fun inject(file: File, installer: File): File {
|
||||||
|
return injectInternal(move(file), installer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
private fun injectInternal(file: File, installer: File): File {
|
||||||
|
val input = ZipInputStream(file.inputStream())
|
||||||
|
val output = ZipOutputStream(destination.outputStream())
|
||||||
|
|
||||||
|
withStreams(input, output) { zin, zout ->
|
||||||
|
zout.putNextEntry(ZipEntry("META-INF/"))
|
||||||
|
zout.putNextEntry(ZipEntry("META-INF/com/"))
|
||||||
|
zout.putNextEntry(ZipEntry("META-INF/com/google/"))
|
||||||
|
zout.putNextEntry(ZipEntry("META-INF/com/google/android/"))
|
||||||
|
zout.putNextEntry(ZipEntry("META-INF/com/google/android/update-binary"))
|
||||||
|
installer.inputStream().copyTo(zout).also { zout.flush() }
|
||||||
|
|
||||||
|
zout.putNextEntry(ZipEntry("META-INF/com/google/android/updater-script"))
|
||||||
|
zout.write("#MAGISK\n".toByteArray(charset("UTF-8")))
|
||||||
|
|
||||||
|
var off = -1
|
||||||
|
var entry: ZipEntry? = zin.nextEntry
|
||||||
|
while (entry != null) {
|
||||||
|
if (off < 0) {
|
||||||
|
off = entry.name.indexOf('/') + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
val path = entry.name.substring(off)
|
||||||
|
if (path.isNotEmpty() && !path.startsWith("META-INF")) {
|
||||||
|
zout.putNextEntry(ZipEntry(path))
|
||||||
|
if (!entry.isDirectory) {
|
||||||
|
zin.copyTo(zout).also { zout.flush() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = zin.nextEntry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.delete()
|
||||||
|
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun move(file: File) = context.cachedFile("temp").apply {
|
||||||
|
file.renameTo(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,20 +9,17 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.data.repository.FileRepository
|
import com.topjohnwu.magisk.data.repository.FileRepository
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
||||||
import com.topjohnwu.magisk.utils.cachedFile
|
|
||||||
import com.topjohnwu.magisk.utils.withStreams
|
|
||||||
import com.topjohnwu.magisk.utils.writeToCachedFile
|
import com.topjohnwu.magisk.utils.writeToCachedFile
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.view.Notifications
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
import org.koin.android.ext.android.get
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.zip.ZipEntry
|
|
||||||
import java.util.zip.ZipInputStream
|
|
||||||
import java.util.zip.ZipOutputStream
|
|
||||||
|
|
||||||
abstract class RemoteFileService : NotificationService() {
|
abstract class RemoteFileService : NotificationService() {
|
||||||
|
|
||||||
@ -40,7 +37,7 @@ abstract class RemoteFileService : NotificationService() {
|
|||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
private fun startInternal(subject: DownloadSubject) = search(subject)
|
private fun startInternal(subject: DownloadSubject): Single<File> = search(subject)
|
||||||
.onErrorResumeNext(download(subject))
|
.onErrorResumeNext(download(subject))
|
||||||
.doOnSubscribe { update(subject.hashCode()) { it.setContentTitle(subject.fileName) } }
|
.doOnSubscribe { update(subject.hashCode()) { it.setContentTitle(subject.fileName) } }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -76,57 +73,22 @@ abstract class RemoteFileService : NotificationService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun download(subject: DownloadSubject) = repo.downloadFile(subject.url)
|
private fun download(subject: DownloadSubject) = repo.downloadFile(subject.url)
|
||||||
|
.map { it.toFile(subject.hashCode(), subject.fileName) }
|
||||||
.map {
|
.map {
|
||||||
when (subject) {
|
when (subject) {
|
||||||
is Module -> appendInstaller(it, subject)
|
is Module -> {
|
||||||
else -> it.toFile(subject.hashCode(), subject.fileName)
|
update(subject.hashCode()) {
|
||||||
}
|
it.setContentText(getString(R.string.download_module))
|
||||||
}
|
.setProgress(0, 0, true)
|
||||||
|
|
||||||
private fun appendInstaller(body: ResponseBody, subject: DownloadSubject): File {
|
|
||||||
update(subject.hashCode()) {
|
|
||||||
it.setContentText(getString(R.string.download_module))
|
|
||||||
}
|
|
||||||
|
|
||||||
val installer = startInternal(Installer).blockingGet()
|
|
||||||
val target = cachedFile(subject.fileName)
|
|
||||||
|
|
||||||
val input = ZipInputStream(body.byteStream())
|
|
||||||
val output = ZipOutputStream(target.outputStream())
|
|
||||||
|
|
||||||
withStreams(input, output) { zin, zout ->
|
|
||||||
zout.putNextEntry(ZipEntry("META-INF/"))
|
|
||||||
zout.putNextEntry(ZipEntry("META-INF/com/"))
|
|
||||||
zout.putNextEntry(ZipEntry("META-INF/com/google/"))
|
|
||||||
zout.putNextEntry(ZipEntry("META-INF/com/google/android/"))
|
|
||||||
zout.putNextEntry(ZipEntry("META-INF/com/google/android/update-binary"))
|
|
||||||
installer.inputStream().copyTo(zout).also { zout.flush() }
|
|
||||||
|
|
||||||
zout.putNextEntry(ZipEntry("META-INF/com/google/android/updater-script"))
|
|
||||||
zout.write("#MAGISK\n".toByteArray(charset("UTF-8")))
|
|
||||||
|
|
||||||
var off = -1
|
|
||||||
var entry: ZipEntry? = zin.nextEntry
|
|
||||||
while (entry != null) {
|
|
||||||
if (off < 0) {
|
|
||||||
off = entry.name.indexOf('/') + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
val path = entry.name.substring(off)
|
|
||||||
if (path.isNotEmpty() && !path.startsWith("META-INF")) {
|
|
||||||
zout.putNextEntry(ZipEntry(path))
|
|
||||||
if (!entry.isDirectory) {
|
|
||||||
zin.copyTo(zout).also { zout.flush() }
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
entry = zin.nextEntry
|
get<ModuleTransformer> { parametersOf(subject) }
|
||||||
|
.inject(it, startInternal(Installer).blockingGet())
|
||||||
|
}
|
||||||
|
else -> it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
private fun ResponseBody.toFile(id: Int, name: String): File {
|
private fun ResponseBody.toFile(id: Int, name: String): File {
|
||||||
|
Loading…
Reference in New Issue
Block a user