mirror of
https://github.com/topjohnwu/Magisk
synced 2025-10-27 04:02:14 +01:00
Compare commits
47 Commits
canary-270
...
v28.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
218327f92b | ||
|
|
4eae66a1a7 | ||
|
|
b09ceeb43c | ||
|
|
4fb539c110 | ||
|
|
849b284da5 | ||
|
|
895b5f6cbf | ||
|
|
cb3d4ea514 | ||
|
|
0d89a2a97d | ||
|
|
3ca5913055 | ||
|
|
df6b808f49 | ||
|
|
09c7ac754b | ||
|
|
805da67c23 | ||
|
|
3c6889505b | ||
|
|
c8e9ce7627 | ||
|
|
837c679a31 | ||
|
|
06616659b8 | ||
|
|
a34c04f999 | ||
|
|
da43ac89a0 | ||
|
|
830fc758b9 | ||
|
|
0f3cfef278 | ||
|
|
b32d7bfafd | ||
|
|
c0899f2939 | ||
|
|
082330808f | ||
|
|
024da05888 | ||
|
|
377b6d0cc2 | ||
|
|
c661009b31 | ||
|
|
613f2d31c5 | ||
|
|
7dbb973db5 | ||
|
|
f4502f8be8 | ||
|
|
455b13b83c | ||
|
|
8b98709743 | ||
|
|
1b12f45f39 | ||
|
|
a5cad532ff | ||
|
|
070719db50 | ||
|
|
28cccdf7aa | ||
|
|
b7e0986a5c | ||
|
|
da709745dd | ||
|
|
8b6771d487 | ||
|
|
e1b847fbc5 | ||
|
|
7188de1205 | ||
|
|
44fb7dbcbe | ||
|
|
8086b5933c | ||
|
|
7f675f4bf7 | ||
|
|
5e6b53e0da | ||
|
|
5b29fefc65 | ||
|
|
16a168535d | ||
|
|
33f70f8f6d |
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
@@ -6,7 +6,7 @@ inputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set up JDK 17
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
|
||||
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -83,10 +83,10 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
|
||||
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
|
||||
type: [""]
|
||||
include:
|
||||
- version: 35
|
||||
- version: "Baklava"
|
||||
type: "google_apis"
|
||||
|
||||
steps:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,6 +14,7 @@ native/out
|
||||
*.iml
|
||||
.gradle
|
||||
.idea
|
||||
.kotlin
|
||||
/local.properties
|
||||
/build
|
||||
/captures
|
||||
|
||||
@@ -20,9 +20,9 @@ Some highlight features:
|
||||
|
||||
Click the icon below to download Magisk apk.
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-27008)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.1)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.1)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-28003)
|
||||
|
||||
## Useful Links
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ plugins {
|
||||
id("androidx.navigation.safeargs.kotlin")
|
||||
}
|
||||
|
||||
setupAppCommon()
|
||||
setupMainApk()
|
||||
|
||||
kapt {
|
||||
correctErrorTypes = true
|
||||
@@ -18,27 +18,6 @@ kapt {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.topjohnwu.magisk"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.topjohnwu.magisk"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
versionName = Config.version
|
||||
versionCode = Config.versionCode
|
||||
ndk {
|
||||
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
|
||||
debugSymbolLevel = "FULL"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
proguardFiles("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
dataBinding = true
|
||||
}
|
||||
@@ -46,6 +25,13 @@ android {
|
||||
compileOptions {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package com.topjohnwu.magisk.dialog
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.topjohnwu.magisk.core.BuildConfig
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.R
|
||||
import com.topjohnwu.magisk.core.ktx.reboot
|
||||
import com.topjohnwu.magisk.core.ktx.toast
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.magisk.events.DialogBuilder
|
||||
import com.topjohnwu.magisk.ui.home.HomeViewModel
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : DialogBuilder {
|
||||
@@ -27,9 +32,15 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
|
||||
setCancelable(false)
|
||||
}
|
||||
dialog.activity.lifecycleScope.launch {
|
||||
MagiskInstaller.FixEnv {
|
||||
MagiskInstaller.FixEnv().exec { success ->
|
||||
dialog.dismiss()
|
||||
}.exec()
|
||||
context.toast(
|
||||
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
if (success)
|
||||
UiThreadHandler.handler.postDelayed(5000) { reboot() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package com.topjohnwu.magisk.dialog
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.topjohnwu.magisk.arch.NavigationActivity
|
||||
import com.topjohnwu.magisk.arch.UIActivity
|
||||
import com.topjohnwu.magisk.core.R
|
||||
import com.topjohnwu.magisk.core.ktx.toast
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.magisk.events.DialogBuilder
|
||||
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class UninstallDialog : DialogBuilder {
|
||||
|
||||
@@ -19,7 +21,7 @@ class UninstallDialog : DialogBuilder {
|
||||
setMessage(R.string.uninstall_magisk_msg)
|
||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
text = R.string.restore_img
|
||||
onClick { restore(dialog.context) }
|
||||
onClick { restore(dialog.activity) }
|
||||
}
|
||||
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
text = R.string.complete_uninstall
|
||||
@@ -29,18 +31,20 @@ class UninstallDialog : DialogBuilder {
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun restore(context: Context) {
|
||||
val dialog = ProgressDialog(context).apply {
|
||||
setMessage(context.getString(R.string.restore_img_msg))
|
||||
private fun restore(activity: UIActivity<*>) {
|
||||
val dialog = ProgressDialog(activity).apply {
|
||||
setMessage(activity.getString(R.string.restore_img_msg))
|
||||
show()
|
||||
}
|
||||
|
||||
Shell.cmd("restore_imgs").submit { result ->
|
||||
dialog.dismiss()
|
||||
if (result.isSuccess) {
|
||||
context.toast(R.string.restore_done, Toast.LENGTH_SHORT)
|
||||
} else {
|
||||
context.toast(R.string.restore_fail, Toast.LENGTH_LONG)
|
||||
activity.lifecycleScope.launch {
|
||||
MagiskInstaller.Restore().exec { success ->
|
||||
dialog.dismiss()
|
||||
if (success) {
|
||||
activity.toast(R.string.restore_done, Toast.LENGTH_SHORT)
|
||||
} else {
|
||||
activity.toast(R.string.restore_fail, Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
defaultOrientation = activity?.requestedOrientation ?: -1
|
||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||
if (savedInstanceState == null) {
|
||||
viewModel.startFlashing()
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.core.view.isVisible
|
||||
@@ -16,8 +17,6 @@ import com.topjohnwu.magisk.arch.BaseFragment
|
||||
import com.topjohnwu.magisk.arch.viewModel
|
||||
import com.topjohnwu.magisk.core.ktx.toast
|
||||
import com.topjohnwu.magisk.databinding.FragmentActionMd2Binding
|
||||
import com.topjohnwu.magisk.ui.flash.FlashViewModel
|
||||
import timber.log.Timber
|
||||
import com.topjohnwu.magisk.core.R as CoreR
|
||||
|
||||
class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
||||
@@ -37,39 +36,32 @@ class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
||||
super.onStart()
|
||||
activity?.setTitle(viewModel.args.name)
|
||||
binding.closeBtn.setOnClickListener {
|
||||
activity?.onBackPressed();
|
||||
activity?.onBackPressed()
|
||||
}
|
||||
|
||||
viewModel.state.observe(this) {
|
||||
activity?.supportActionBar?.setSubtitle(
|
||||
when (it) {
|
||||
ActionViewModel.State.RUNNING -> CoreR.string.running
|
||||
ActionViewModel.State.SUCCESS -> CoreR.string.done
|
||||
ActionViewModel.State.FAILED -> CoreR.string.failure
|
||||
if (it != ActionViewModel.State.RUNNING) {
|
||||
binding.closeBtn.apply {
|
||||
if (!this.isVisible) this.show()
|
||||
if (!this.isFocused) this.requestFocus()
|
||||
}
|
||||
}
|
||||
if (it != ActionViewModel.State.SUCCESS) return@observe
|
||||
view?.viewTreeObserver?.addOnWindowFocusChangeListener(
|
||||
object : ViewTreeObserver.OnWindowFocusChangeListener {
|
||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||
if (hasFocus) return
|
||||
view?.viewTreeObserver?.removeOnWindowFocusChangeListener(this)
|
||||
view?.context?.apply {
|
||||
toast(
|
||||
getString(CoreR.string.done_action, viewModel.args.name),
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
}
|
||||
viewModel.back()
|
||||
}
|
||||
}
|
||||
)
|
||||
when (it) {
|
||||
ActionViewModel.State.SUCCESS -> {
|
||||
activity?.apply {
|
||||
toast(
|
||||
getString(
|
||||
com.topjohnwu.magisk.core.R.string.done_action,
|
||||
this@ActionFragment.viewModel.args.name
|
||||
), Toast.LENGTH_LONG
|
||||
)
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
ActionViewModel.State.FAILED -> {
|
||||
binding.closeBtn.apply {
|
||||
if (!this.isVisible) this.show()
|
||||
if (!this.isFocused) this.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +77,7 @@ class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
defaultOrientation = activity?.requestedOrientation ?: -1
|
||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||
if (savedInstanceState == null) {
|
||||
viewModel.startRunAction()
|
||||
}
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
package com.topjohnwu.magisk.ui.module
|
||||
|
||||
import android.view.MenuItem
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.databinding.ObservableArrayList
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.ktx.synchronized
|
||||
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
|
||||
import com.topjohnwu.magisk.core.ktx.toTime
|
||||
import com.topjohnwu.magisk.core.tasks.RunAction
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.ui.flash.ConsoleItem
|
||||
import com.topjohnwu.superuser.CallbackList
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
|
||||
class ActionViewModel : BaseViewModel() {
|
||||
|
||||
@@ -32,7 +30,6 @@ class ActionViewModel : BaseViewModel() {
|
||||
|
||||
private val _state = MutableLiveData(State.RUNNING)
|
||||
val state: LiveData<State> get() = _state
|
||||
val running = state.map { it == State.RUNNING }
|
||||
|
||||
val items = ObservableArrayList<ConsoleItem>()
|
||||
lateinit var args: ActionFragmentArgs
|
||||
@@ -46,10 +43,17 @@ class ActionViewModel : BaseViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun startRunAction() {
|
||||
viewModelScope.launch {
|
||||
onResult(RunAction(args.id, outItems, logItems).exec())
|
||||
}
|
||||
fun startRunAction() = viewModelScope.launch {
|
||||
onResult(withContext(Dispatchers.IO) {
|
||||
try {
|
||||
Shell.cmd("run_action \'${args.id}\'")
|
||||
.to(outItems, logItems)
|
||||
.exec().isSuccess
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun onResult(success: Boolean) {
|
||||
|
||||
@@ -19,6 +19,7 @@ android {
|
||||
buildConfigField("int", "APP_VERSION_CODE", "${Config.versionCode}")
|
||||
buildConfigField("String", "APP_VERSION_NAME", "\"${Config.version}\"")
|
||||
buildConfigField("int", "STUB_VERSION", Config.stubVersion)
|
||||
consumerProguardFile("proguard-rules.pro")
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
|
||||
@@ -22,36 +22,21 @@
|
||||
int mActivityHandlesConfigFlags;
|
||||
}
|
||||
|
||||
# main
|
||||
-keep,allowoptimization public class com.topjohnwu.magisk.signing.SignBoot {
|
||||
public static void main(java.lang.String[]);
|
||||
}
|
||||
|
||||
# Strip Timber verbose and debug logging
|
||||
-assumenosideeffects class timber.log.Timber$Tree {
|
||||
public void v(**);
|
||||
public void d(**);
|
||||
}
|
||||
|
||||
# https://github.com/square/retrofit/issues/3751#issuecomment-1192043644
|
||||
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
|
||||
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
|
||||
-keep,allowobfuscation,allowshrinking class retrofit2.Response
|
||||
|
||||
# With R8 full mode generic signatures are stripped for classes that are not
|
||||
# kept. Suspend functions are wrapped in continuations where the type argument
|
||||
# is used.
|
||||
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
|
||||
|
||||
|
||||
# Excessive obfuscation
|
||||
-repackageclasses 'a'
|
||||
-flattenpackagehierarchy
|
||||
-allowaccessmodification
|
||||
|
||||
-obfuscationdictionary ../dict.txt
|
||||
-classobfuscationdictionary ../dict.txt
|
||||
-packageobfuscationdictionary ../dict.txt
|
||||
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLParameters
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
||||
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
|
||||
@@ -191,11 +191,12 @@ object AppMigration {
|
||||
|
||||
// Install and auto launch app
|
||||
val session = APKInstall.startSession(activity, pkg, onFailure) {
|
||||
Config.suManager = pkg
|
||||
Shell.cmd("touch $AppApkPath").exec()
|
||||
launchApp(activity, pkg)
|
||||
}
|
||||
|
||||
Config.suManager = pkg
|
||||
val cmd = "touch $AppApkPath; adb_pm_install $repack $pkg"
|
||||
val cmd = "adb_pm_install $repack $pkg"
|
||||
if (Shell.cmd(cmd).exec().isSuccess) return true
|
||||
|
||||
try {
|
||||
@@ -240,11 +241,12 @@ object AppMigration {
|
||||
}
|
||||
val apk = StubApk.current(activity)
|
||||
val session = APKInstall.startSession(activity, APP_PACKAGE_NAME, onFailure) {
|
||||
Config.suManager = ""
|
||||
Shell.cmd("touch $AppApkPath").exec()
|
||||
launchApp(activity, APP_PACKAGE_NAME)
|
||||
dialog.dismiss()
|
||||
}
|
||||
Config.suManager = ""
|
||||
val cmd = "touch $AppApkPath; adb_pm_install $apk $APP_PACKAGE_NAME"
|
||||
val cmd = "adb_pm_install $apk $APP_PACKAGE_NAME"
|
||||
if (Shell.cmd(cmd).await().isSuccess) return
|
||||
val success = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.system.ErrnoException
|
||||
import android.system.Os
|
||||
import android.system.OsConstants
|
||||
import android.system.OsConstants.O_WRONLY
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.os.postDelayed
|
||||
import com.topjohnwu.magisk.StubApk
|
||||
@@ -15,13 +14,10 @@ import com.topjohnwu.magisk.core.BuildConfig
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.R
|
||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.ktx.copyAll
|
||||
import com.topjohnwu.magisk.core.ktx.copyAndClose
|
||||
import com.topjohnwu.magisk.core.ktx.reboot
|
||||
import com.topjohnwu.magisk.core.ktx.toast
|
||||
import com.topjohnwu.magisk.core.ktx.writeTo
|
||||
import com.topjohnwu.magisk.core.utils.DummyList
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
@@ -585,6 +581,8 @@ abstract class MagiskInstallImpl protected constructor(
|
||||
|
||||
protected suspend fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess
|
||||
|
||||
protected fun restore() = findImage() && "restore_imgs $srcBoot".sh().isSuccess
|
||||
|
||||
protected fun uninstall() = "run_uninstaller $AppApkPath".sh().isSuccess
|
||||
|
||||
@WorkerThread
|
||||
@@ -608,11 +606,10 @@ abstract class MagiskInstallImpl protected constructor(
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MagiskInstaller(
|
||||
abstract class ConsoleInstaller(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstallImpl(console, logs) {
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
if (success) {
|
||||
@@ -622,40 +619,51 @@ abstract class MagiskInstaller(
|
||||
}
|
||||
return success
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CallBackInstaller : MagiskInstallImpl(DummyList, DummyList) {
|
||||
suspend fun exec(callback: (Boolean) -> Unit): Boolean {
|
||||
val success = exec()
|
||||
callback(success)
|
||||
return success
|
||||
}
|
||||
}
|
||||
|
||||
class MagiskInstaller {
|
||||
|
||||
class Patch(
|
||||
private val uri: Uri,
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(console, logs) {
|
||||
) : ConsoleInstaller(console, logs) {
|
||||
override suspend fun operations() = patchFile(uri)
|
||||
}
|
||||
|
||||
class SecondSlot(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(console, logs) {
|
||||
) : ConsoleInstaller(console, logs) {
|
||||
override suspend fun operations() = secondSlot()
|
||||
}
|
||||
|
||||
class Direct(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(console, logs) {
|
||||
) : ConsoleInstaller(console, logs) {
|
||||
override suspend fun operations() = direct()
|
||||
}
|
||||
|
||||
class Emulator(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(console, logs) {
|
||||
) : ConsoleInstaller(console, logs) {
|
||||
override suspend fun operations() = fixEnv()
|
||||
}
|
||||
|
||||
class Uninstall(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstallImpl(console, logs) {
|
||||
) : ConsoleInstaller(console, logs) {
|
||||
override suspend fun operations() = uninstall()
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
@@ -669,19 +677,11 @@ abstract class MagiskInstaller(
|
||||
}
|
||||
}
|
||||
|
||||
class FixEnv(private val callback: () -> Unit) : MagiskInstallImpl(DummyList, DummyList) {
|
||||
override suspend fun operations() = fixEnv()
|
||||
class Restore : CallBackInstaller() {
|
||||
override suspend fun operations() = restore()
|
||||
}
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
callback()
|
||||
context.toast(
|
||||
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
if (success)
|
||||
UiThreadHandler.handler.postDelayed(5000) { reboot() }
|
||||
return success
|
||||
}
|
||||
class FixEnv : CallBackInstaller() {
|
||||
override suspend fun operations() = fixEnv()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.tasks
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toFile
|
||||
import com.topjohnwu.magisk.core.AppContext
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.ktx.writeTo
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.displayName
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
|
||||
import com.topjohnwu.magisk.core.utils.unzip
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
|
||||
open class RunAction(
|
||||
private val module: String,
|
||||
private val console: MutableList<String>,
|
||||
private val logs: MutableList<String>
|
||||
) {
|
||||
@Throws(IOException::class)
|
||||
private suspend fun run(): Boolean {
|
||||
return Shell.cmd("run_action \'$module\'").to(console, logs).exec().isSuccess
|
||||
}
|
||||
|
||||
open suspend fun exec() = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
if (!run()) {
|
||||
console.add("! Run action failed")
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.topjohnwu.magisk.core.utils;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class Desugar {
|
||||
public static FileTime getLastModifiedTime(ZipEntry entry) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return entry.getLastModifiedTime();
|
||||
} else {
|
||||
return FileTime.fromMillis(entry.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
public static FileTime getLastAccessTime(ZipEntry entry) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return entry.getLastAccessTime();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static FileTime getCreationTime(ZipEntry entry) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return entry.getCreationTime();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,9 @@
|
||||
<string name="section_theme">עיצוב</string>
|
||||
<string name="denylist">רשימת דחייה</string>
|
||||
|
||||
|
||||
<!--Home-->
|
||||
<string name="no_connection">אין חיבור זמין</string>
|
||||
<string name="app_changelog">רשימת שינויים</string>
|
||||
<string name="app_changelog">יומן שינויים</string>
|
||||
<string name="loading">טוען…</string>
|
||||
<string name="update">עדכון</string>
|
||||
<string name="not_available">ל/ז</string>
|
||||
@@ -45,16 +44,16 @@
|
||||
<string name="install_inactive_slot_msg">ההתקן שלך ייאלץ אתחול לחריץ הלא פעיל הנוכחי שלך לאחר הפעלה מחדש!\nיש להשתמש באפשרות זו רק לאחר ביצוע OTA בלבד.\nלהמשיך?</string>
|
||||
<string name="setup_title">התקנה נוספת</string>
|
||||
<string name="select_patch_file">בחירה והתקנת קובץ</string>
|
||||
<string name="patch_file_msg">בחירת תמונה גולמית (*.img) או ODIN קובץ tar (*.tar)</string>
|
||||
<string name="patch_file_msg">בחירת תמונה גולמית (*.img) או ODIN tarfile (*.tar) או payload.bin (*.bin)</string>
|
||||
<string name="reboot_delay_toast">מאתחל בעוד 5 שניות…</string>
|
||||
<string name="flash_screen_title">התקנה</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">בקשות משתמש על</string>
|
||||
<string name="touch_filtered_warning">מכיוון שיישום מסתיר בקשה של משתמש על, Magisk לא יכול לאמת את תגובתך</string>
|
||||
<string name="deny">דחה</string>
|
||||
<string name="deny">דחייה</string>
|
||||
<string name="prompt">מיידי</string>
|
||||
<string name="grant">הענק</string>
|
||||
<string name="grant">הענקה</string>
|
||||
<string name="su_warning">מעניק גישה מלאה להתקן שלך.\nיש לדחות באי וודאות!</string>
|
||||
<string name="forever">לצמיתות</string>
|
||||
<string name="once">פעם אחת</string>
|
||||
@@ -62,24 +61,24 @@
|
||||
<string name="twentymin">20 דקות</string>
|
||||
<string name="thirtymin">חצי שעה</string>
|
||||
<string name="sixtymin">שעה</string>
|
||||
<string name="su_allow_toast">%1$s הוענקו הרשאות משתמש עבור</string>
|
||||
<string name="su_deny_toast">%1$s נשללו הרשאות משתמש עבור</string>
|
||||
<string name="su_allow_toast">%1$s קיבל הרשאות משתמש על</string>
|
||||
<string name="su_deny_toast">%1$s נשללו הרשאות משתמש על</string>
|
||||
<string name="su_snack_grant">הרשאות משתמש על עבור %1$s הוענקו</string>
|
||||
<string name="su_snack_deny">הרשאות משתמש על עבור %1$s נשללו</string>
|
||||
<string name="su_snack_notif_on">התראות עבור %1$s פועלות</string>
|
||||
<string name="su_snack_notif_off">התראות עבור %1$s כבויות</string>
|
||||
<string name="su_snack_notif_on">התראות של %1$s מופעלות</string>
|
||||
<string name="su_snack_notif_off">התראות של %1$s מושבתות</string>
|
||||
<string name="su_snack_log_on">יומני רישום עבור %1$s פועלות</string>
|
||||
<string name="su_snack_log_off">יומני רישום עבור %1$s כבויות</string>
|
||||
<string name="su_snack_log_off">יומני רישום עבור %1$s מושבתות</string>
|
||||
<string name="su_revoke_title">להסיר?</string>
|
||||
<string name="su_revoke_msg">נא לאשר שלילת הרשאות עבור %1$s?</string>
|
||||
<string name="toast">הרמת כוסית</string>
|
||||
<string name="none">ללא</string>
|
||||
<string name="superuser_toggle_notification">התראות</string>
|
||||
<string name="superuser_toggle_revoke">הסרה</string>
|
||||
<string name="superuser_policy_none">לא נתבקשו הרשאות משתמש על על ידי שום יישום</string>
|
||||
<string name="superuser_policy_none">טרם נתבקשו הרשאות משתמש על על ידי יישומים</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">הינך ללא יומן רישום, יש לנסות להשתמש ביישומים מותאמים יותר למשתמש העל שלך</string>
|
||||
<string name="log_data_none">הינך ללא יומן, יש לנסות להשתמש יותר ביישומי השורש שלך</string>
|
||||
<string name="log_data_magisk_none">יומני רישום Magisk ריקים, זה מוזר</string>
|
||||
<string name="menuSaveLog">שמירת יומן רישום</string>
|
||||
<string name="menuClearLog">ניקוי יומן רישום כעת</string>
|
||||
@@ -92,7 +91,7 @@
|
||||
|
||||
<!--SafetyNet-->
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<!--MagiskHide-->
|
||||
<string name="show_system_app">הצגת יישומי מערכת</string>
|
||||
<string name="show_os_app">הצגת יישומי מערכת הפעלה</string>
|
||||
<string name="hide_filter_hint">סינון לפי שם</string>
|
||||
@@ -100,14 +99,16 @@
|
||||
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(לא סופק מידע)</string>
|
||||
<string name="reboot_userspace">אתחול מהיר</string>
|
||||
<string name="reboot_userspace">אתחול רך</string>
|
||||
<string name="reboot_recovery">אתחול למצב שחזור</string>
|
||||
<string name="reboot_bootloader">אתחול מצב מנהל האתחול</string>
|
||||
<string name="reboot_download">אתחול מצב הורדה</string>
|
||||
<string name="reboot_bootloader">אתחול לטוען האתחול</string>
|
||||
<string name="reboot_download">אתחול למצב הורדה</string>
|
||||
<string name="reboot_edl">אתחול למצב EDL</string>
|
||||
<string name="reboot_safe_mode">מצב בטוח</string>
|
||||
<string name="module_version_author">%1$s מאת %2$s</string>
|
||||
<string name="module_state_remove">הסרה</string>
|
||||
<string name="module_state_restore">שיחזור</string>
|
||||
<string name="module_action">פעולה</string>
|
||||
<string name="module_state_restore">שחזור</string>
|
||||
<string name="module_action_install_external">התקנה מהאחסון</string>
|
||||
<string name="update_available">עדכונים זמינים</string>
|
||||
<string name="suspend_text_riru">מודול מושעה כי %1$s מופעל</string>
|
||||
@@ -117,7 +118,7 @@
|
||||
<string name="confirm_install">להתקין מודול %1$s?</string>
|
||||
<string name="confirm_install_title">אישור התקנה</string>
|
||||
|
||||
<!--Settings -->
|
||||
<!--Settings-->
|
||||
<string name="settings_dark_mode_title">מצב עיצוב</string>
|
||||
<string name="settings_dark_mode_message">נא לבחור מצב המתאים ביותר לסגנון שלך!</string>
|
||||
<string name="settings_dark_mode_light">תמיד בהיר</string>
|
||||
@@ -128,11 +129,11 @@
|
||||
<string name="settings_hide_app_title">הסתרת היישום Magisk</string>
|
||||
<string name="settings_hide_app_summary">התקנת יישום מתווך עם מזהה חבילה אקראי ותווית שם מותאמת אישית</string>
|
||||
<string name="settings_restore_app_title">שיחזור היישום Magisk</string>
|
||||
<string name="settings_restore_app_summary">יש לבטל את הסתרת היישום ולשחזור אותו ל-APK המקורי</string>
|
||||
<string name="settings_restore_app_summary">ביטול הסתרת היישום ושחזור אל ה-APK המקורי</string>
|
||||
<string name="language">שפה</string>
|
||||
<string name="system_default">(ברירת מחדל מערכת)</string>
|
||||
<string name="settings_check_update_title">בדיקת עדכונים</string>
|
||||
<string name="settings_check_update_summary">בדוק מעת לעת ברקע אם יש עדכונים</string>
|
||||
<string name="settings_check_update_summary">בדיקה מעת לעת ברקע אם יש עדכונים</string>
|
||||
<string name="settings_update_channel_title">ערוץ עדכון</string>
|
||||
<string name="settings_update_stable">יציב</string>
|
||||
<string name="settings_update_beta">בטא</string>
|
||||
@@ -161,12 +162,12 @@
|
||||
<string name="settings_su_request_60">60 שניות</string>
|
||||
<string name="superuser_access">גישת משתמש על</string>
|
||||
<string name="auto_response">תגובה אוטומטית</string>
|
||||
<string name="request_timeout">בקש פסק זמן</string>
|
||||
<string name="request_timeout">בקשת פסק זמן</string>
|
||||
<string name="superuser_notification">התראות משתמש על</string>
|
||||
<string name="settings_su_reauth_title">אימות מחדש לאחר שדרוג</string>
|
||||
<string name="settings_su_reauth_summary">אימות מחדש הרשאות של משתמש על לאחר שדרוג יישום</string>
|
||||
<string name="settings_su_tapjack_title">הפעלת הגנת Tapjacking</string>
|
||||
<string name="settings_su_tapjack_summary">תיבת הדו שיח של משתמש העל לא תגיב לקלט כשהיא מוסתרת על ידי חלון או כיסוי אחר</string>
|
||||
<string name="settings_su_tapjack_title">הגנת Tapjacking</string>
|
||||
<string name="settings_su_tapjack_summary">תיבת הדו שיח של משתמש העל לא תגיב לקלט כשהיא מוסתרת על ידי חלון או שכבת על אחרת</string>
|
||||
<string name="settings_su_auth_title">אימות משתמש</string>
|
||||
<string name="settings_su_auth_summary">בקשת אימות משתמש במהלך בקשות משתמש על</string>
|
||||
<string name="settings_su_auth_insecure">לא מוגדרת שיטת אימות בהתקן</string>
|
||||
@@ -174,6 +175,8 @@
|
||||
<string name="setting_add_shortcut_summary">הוספת קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת היישום</string>
|
||||
<string name="settings_doh_title">DNS על HTTPS</string>
|
||||
<string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string>
|
||||
<string name="settings_random_name_title">שם פלט אקראי</string>
|
||||
<string name="settings_random_name_description">שם אקראי לקובץ הפלט של תמונות מתוקנות וקבצי tar כדי למנוע זיהוי</string>
|
||||
<string name="multiuser_mode">מצב מרובה משתמשים</string>
|
||||
<string name="settings_owner_only">בעל ההתקן בלבד</string>
|
||||
<string name="settings_owner_manage">אחראי ניהול ההתקן</string>
|
||||
@@ -205,10 +208,13 @@
|
||||
<string name="repo_install_title">מתקין %1$s %2$s(%3$d)</string>
|
||||
<string name="download">הורדה</string>
|
||||
<string name="reboot">הפעלה מחדש</string>
|
||||
<string name="close">סגירה</string>
|
||||
<string name="release_notes">הערות שחרור</string>
|
||||
<string name="flashing">צורב…</string>
|
||||
<string name="running">רץ…</string>
|
||||
<string name="done">בוצע!</string>
|
||||
<string name="failure">נכשל</string>
|
||||
<string name="done_action">בוצעה ריצת פעולה של %1$s</string>
|
||||
<string name="failure">נכשל!</string>
|
||||
<string name="hide_app_title">מסתיר את יישום Magisk…</string>
|
||||
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
|
||||
<string name="complete_uninstall">הסרה מלאה</string>
|
||||
@@ -237,4 +243,5 @@
|
||||
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
|
||||
<string name="reboot_apply_change">ייש להפעיל מחדש כדי להחיל שינויים</string>
|
||||
<string name="restore_app_confirmation">פעולה זו תשחזר את היישום המוסתר חזרה ליישום המקורי. האם בוודאות ברצונך לעשות את זה?</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
<string name="logs_cleared">Логи успешно очищены</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Целевой UID: %1$d</string>
|
||||
<string name="target_pid">Целевой PID пространства имён: %s</string>
|
||||
<string name="selinux_context">Контекст SELinux: %s</string>
|
||||
<string name="supp_group">Дополнительная группа: %s</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
|
||||
@@ -164,11 +167,16 @@
|
||||
<string name="settings_su_reauth_title">Повторная аутентификация</string>
|
||||
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений</string>
|
||||
<string name="settings_su_tapjack_title">Защита от перехвата нажатий</string>
|
||||
<string name="settings_su_auth_title">Аутентификация пользователя</string>
|
||||
<string name="settings_su_auth_summary">Требовать аутентификацию пользователя при запросах Superuser</string>
|
||||
<string name="settings_su_auth_insecure">На устройстве не настроен метод аутентификации</string>
|
||||
<string name="settings_su_tapjack_summary">Окно запроса прав суперпользователя будет неактивно пока активированы наложения экрана</string>
|
||||
<string name="settings_customization">Персонализация</string>
|
||||
<string name="setting_add_shortcut_summary">Добавить ярлык на рабочий стол для удобного восприятия приложения после его скрытия</string>
|
||||
<string name="settings_doh_title">DNS поверх HTTPS</string>
|
||||
<string name="settings_doh_description">Активировать DoH (используйте при проблемах с подключением к сети)</string>
|
||||
<string name="settings_random_name_title">Случайное имя образа</string>
|
||||
<string name="settings_random_name_description">Генерировать случайные имена для патченных образов и tar-файлов для предотвращения обнаружения</string>
|
||||
|
||||
<string name="multiuser_mode">Многопользовательский режим</string>
|
||||
<string name="settings_owner_only">Только администратор</string>
|
||||
|
||||
@@ -130,8 +130,8 @@
|
||||
<string name="settings_update_custom">Власний</string>
|
||||
<string name="settings_update_custom_msg">Вставте власний URL</string>
|
||||
<string name="settings_zygisk_summary">Запускати частини Magisk в сервісі zygote</string>
|
||||
<string name="settings_denylist_title">Enforce DenyList</string>
|
||||
<string name="settings_denylist_summary">Processes on the denylist will have all Magisk modifications reverted</string>
|
||||
<string name="settings_denylist_title">Увімкнути DenyList</string>
|
||||
<string name="settings_denylist_summary">Всі зміни, внесені Magisk, будуть приховані від процесів, позначених у DenyList</string>
|
||||
<string name="settings_denylist_config_title">Налаштувати DenyList</string>
|
||||
<string name="settings_denylist_config_summary">Вибрати процеси, які будуть додані до denylist</string>
|
||||
<string name="settings_hosts_title">Позасистемні хости</string>
|
||||
@@ -156,7 +156,7 @@
|
||||
<string name="superuser_notification">Сповіщення суперкористувача</string>
|
||||
<string name="settings_su_reauth_title">Повторна автентифікація</string>
|
||||
<string name="settings_su_reauth_summary">Перевидача прав суперкористувача після оновлення застосунку</string>
|
||||
<string name="settings_su_tapjack_title">Увімкнути захист від Tapjack</string>
|
||||
<string name="settings_su_tapjack_title">Увімкнути захист від підміни натискань</string>
|
||||
<string name="settings_su_tapjack_summary">Діалогове вікно суперкористувача не буде отримувати ввід від користувача, коли вікно перекрито іншим застосунком чи вікном</string>
|
||||
<string name="settings_customization">Оформлення</string>
|
||||
<string name="setting_add_shortcut_summary">Додати ярлик на домашній екран для зручного сприйняття застосунку після його приховування</string>
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
<string name="reboot_safe_mode">安全模式</string>
|
||||
<string name="module_version_author">%1$s,作者 %2$s</string>
|
||||
<string name="module_state_remove">移除</string>
|
||||
<string name="module_action">操作</string>
|
||||
<string name="module_state_restore">还原</string>
|
||||
<string name="module_action_install_external">从本地安装</string>
|
||||
<string name="update_available">可更新</string>
|
||||
@@ -211,9 +212,12 @@
|
||||
<string name="repo_install_title">安装 %1$s %2$s(%3$d)</string>
|
||||
<string name="download">下载</string>
|
||||
<string name="reboot">重启</string>
|
||||
<string name="close">关闭</string>
|
||||
<string name="release_notes">发布说明</string>
|
||||
<string name="flashing">正在刷入</string>
|
||||
<string name="running">运行中……</string>
|
||||
<string name="done">完成!</string>
|
||||
<string name="done_action">%1$s 操作运行完成</string>
|
||||
<string name="failure">失败</string>
|
||||
<string name="hide_app_title">正在隐藏 Magisk 应用</string>
|
||||
<string name="open_link_failed_toast">找不到能打开此链接的应用</string>
|
||||
|
||||
@@ -15,7 +15,7 @@ android {
|
||||
val canary = !Config.version.contains(".")
|
||||
|
||||
val url = if (canary) null
|
||||
else "https://cdn.jsdelivr.net/gh/topjohnwu/magisk-files@${Config.version}/app-release.apk"
|
||||
else "https://github.com/topjohnwu/Magisk/releases/download/v${Config.version}/Magisk-v${Config.version}.apk"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.topjohnwu.magisk"
|
||||
@@ -27,9 +27,9 @@ android {
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
proguardFiles("proguard-rules.pro")
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = false
|
||||
proguardFiles("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
setupStub()
|
||||
setupStubApk()
|
||||
|
||||
dependencies {
|
||||
implementation(project(":app:shared"))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
@@ -18,9 +18,9 @@ gradlePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
kotlinOptions {
|
||||
languageVersion = "2.0"
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
languageVersion = KotlinVersion.KOTLIN_2_0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
78
buildSrc/src/main/java/DesugarClassVisitorFactory.kt
Normal file
78
buildSrc/src/main/java/DesugarClassVisitorFactory.kt
Normal file
@@ -0,0 +1,78 @@
|
||||
import com.android.build.api.instrumentation.AsmClassVisitorFactory
|
||||
import com.android.build.api.instrumentation.ClassContext
|
||||
import com.android.build.api.instrumentation.ClassData
|
||||
import com.android.build.api.instrumentation.InstrumentationParameters
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.MethodVisitor
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.Opcodes.ASM9
|
||||
|
||||
private const val ZIP_ENTRY_CLASS_NAME = "java.util.zip.ZipEntry"
|
||||
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
|
||||
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
|
||||
private const val DESUGAR_GET_TIME_DESC =
|
||||
"(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
|
||||
|
||||
private fun ClassData.isTypeOf(name: String) = className == name || superClasses.contains(name)
|
||||
|
||||
abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
|
||||
override fun createClassVisitor(
|
||||
classContext: ClassContext,
|
||||
nextClassVisitor: ClassVisitor
|
||||
): ClassVisitor {
|
||||
return DesugarClassVisitor(classContext, nextClassVisitor)
|
||||
}
|
||||
|
||||
override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
|
||||
|
||||
class DesugarClassVisitor(private val classContext: ClassContext, cv: ClassVisitor) :
|
||||
ClassVisitor(ASM9, cv) {
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String?,
|
||||
descriptor: String?,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor {
|
||||
return DesugarMethodVisitor(
|
||||
super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||
)
|
||||
}
|
||||
|
||||
inner class DesugarMethodVisitor(mv: MethodVisitor?) :
|
||||
MethodVisitor(ASM9, mv) {
|
||||
override fun visitMethodInsn(
|
||||
opcode: Int,
|
||||
owner: String,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
isInterface: Boolean
|
||||
) {
|
||||
if (!process(owner, name, descriptor)) {
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
|
||||
}
|
||||
}
|
||||
|
||||
private fun process(owner: String, name: String, descriptor: String): Boolean {
|
||||
val classData = classContext.loadClassData(owner.replace("/", ".")) ?: return false
|
||||
if (!classData.isTypeOf(ZIP_ENTRY_CLASS_NAME))
|
||||
return false
|
||||
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
|
||||
return false
|
||||
return when (name) {
|
||||
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
DESUGAR_CLASS_NAME.replace('.', '/'),
|
||||
name,
|
||||
DESUGAR_GET_TIME_DESC,
|
||||
false
|
||||
)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import com.android.build.api.artifact.ArtifactTransformationRequest
|
||||
import com.android.build.api.artifact.SingleArtifact
|
||||
import com.android.build.api.dsl.ApkSigningConfig
|
||||
import com.android.build.api.instrumentation.FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS
|
||||
import com.android.build.api.instrumentation.InstrumentationScope
|
||||
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
@@ -15,6 +17,7 @@ import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Copy
|
||||
@@ -114,9 +117,9 @@ fun Project.setupCommon() {
|
||||
}
|
||||
|
||||
const val BUSYBOX_DOWNLOAD_URL =
|
||||
"https://github.com/topjohnwu/magisk-files/releases/download/files/busybox-1.36.1.0.zip"
|
||||
"https://github.com/topjohnwu/magisk-files/releases/download/files/busybox-1.36.1.1.zip"
|
||||
const val BUSYBOX_ZIP_CHECKSUM =
|
||||
"ea4f3019b0087dcb68130b32ab59dc2db0ee0af11d8396124a94c4231c5ea441"
|
||||
"b4d0551feabaf314e53c79316c980e8f66432e9fb91a69dbbf10a93564b40951"
|
||||
|
||||
fun Project.setupCoreLib() {
|
||||
setupCommon()
|
||||
@@ -348,7 +351,34 @@ fun Project.setupAppCommon() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.setupStub() {
|
||||
fun Project.setupMainApk() {
|
||||
setupAppCommon()
|
||||
|
||||
android {
|
||||
namespace = "com.topjohnwu.magisk"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.topjohnwu.magisk"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
versionName = Config.version
|
||||
versionCode = Config.versionCode
|
||||
ndk {
|
||||
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
|
||||
debugSymbolLevel = "FULL"
|
||||
}
|
||||
}
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
variant.instrumentation.apply {
|
||||
setAsmFramesComputationMode(COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS)
|
||||
transformClassesWith(
|
||||
DesugarClassVisitorFactory::class.java, InstrumentationScope.ALL) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.setupStubApk() {
|
||||
setupAppCommon()
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# Magisk Changelog
|
||||
|
||||
### v28.1
|
||||
|
||||
- [App] Fix stub APK download link
|
||||
- [App] Fix support for Android lower than 8.0
|
||||
- [General] Fix support for MTK Samsung devices
|
||||
- [MagiskInit] Fix a regression for 2SI devices
|
||||
- [MagiskPolicy] Fix a regression causing `overlay.d` replaced files to be not accessible
|
||||
|
||||
### v28.0
|
||||
|
||||
- [General] Support 16k page size
|
||||
- [General] Add basic support for RISC-V (not built in releases)
|
||||
- [General] Use a minimal libc to build static executables (`magiskinit` and `magiskboot`) for smaller sizes
|
||||
- [Core] Remove unnecessary mirror for magic mount
|
||||
- [Core] Update boot image detection logic to support more devices
|
||||
- [MagiskInit] Rewrite 2SI logic for injecting `magiskinit` as `init`
|
||||
- [MagiskInit] Update preinit partition detection
|
||||
- [Zygisk] Update internal JNI hooking implementation
|
||||
- [MagiskPolicy] Preserve sepolicy config flag after patching
|
||||
- [MagiskPolicy] Optimize patching rules to reduce the amount of new rules being injected
|
||||
- [DenyList] Support enforcing denylist when Zygisk is disabled
|
||||
- [Resetprop] Improve implementation to workaround several property modification detections
|
||||
- [Resetprop] Update to properly work with property overlays
|
||||
- [App] Major internal code refactoring
|
||||
- [App] Support patching Samsung firmware with images larger than 8GiB
|
||||
- [App] Use user-initiated job instead of foreground services on Android 14
|
||||
- [App] Support Android 13+ built-in per-app language preferences
|
||||
- [App] Add `action.sh` support to allow modules to define an action triggered from UI
|
||||
- [MagiskBoot] Support spliting kernel images without decompression
|
||||
- [MagiskBoot] Properly support vendor boot images
|
||||
- [MagiskBoot] Disable Samsung PROCA from kernel image
|
||||
|
||||
### v27.0
|
||||
|
||||
- [Zygisk] Introduce new code injection mechanism
|
||||
|
||||
25
docs/releases/28000.md
Normal file
25
docs/releases/28000.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## 2024.10.10 Magisk v28.0
|
||||
|
||||
- [General] Support 16k page size
|
||||
- [General] Add basic support for RISC-V (not built in releases)
|
||||
- [General] Use a minimal libc to build static executables (`magiskinit` and `magiskboot`) for smaller sizes
|
||||
- [Core] Remove unnecessary mirror for magic mount
|
||||
- [Core] Update boot image detection logic to support more devices
|
||||
- [MagiskInit] Rewrite 2SI logic for injecting `magiskinit` as `init`
|
||||
- [MagiskInit] Update preinit partition detection
|
||||
- [Zygisk] Update internal JNI hooking implementation
|
||||
- [MagiskPolicy] Preserve sepolicy config flag after patching
|
||||
- [MagiskPolicy] Optimize patching rules to reduce the amount of new rules being injected
|
||||
- [DenyList] Support enforcing denylist when Zygisk is disabled
|
||||
- [Resetprop] Improve implementation to workaround several property modification detections
|
||||
- [Resetprop] Update to properly work with property overlays
|
||||
- [App] Major internal code refactoring
|
||||
- [App] Support patching Samsung firmware with images larger than 8GiB
|
||||
- [App] Use user-initiated job instead of foreground services on Android 14
|
||||
- [App] Support Android 13+ built-in per-app language preferences
|
||||
- [App] Add `action.sh` support to allow modules to define an action triggered from UI
|
||||
- [MagiskBoot] Support spliting kernel images without decompression
|
||||
- [MagiskBoot] Properly support vendor boot images
|
||||
- [MagiskBoot] Disable Samsung PROCA from kernel image
|
||||
|
||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
||||
33
docs/releases/28100.md
Normal file
33
docs/releases/28100.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## 2024.12.6 Magisk v28.1
|
||||
|
||||
- [App] Fix stub APK download link
|
||||
- [App] Fix support for Android lower than 8.0
|
||||
- [General] Fix support for MTK Samsung devices
|
||||
- [MagiskInit] Fix a regression for 2SI devices
|
||||
- [MagiskPolicy] Fix a regression causing `overlay.d` replaced files to be not accessible
|
||||
|
||||
## Magisk v28.0 Changes
|
||||
|
||||
- [General] Support 16k page size
|
||||
- [General] Add basic support for RISC-V (not built in releases)
|
||||
- [General] Use a minimal libc to build static executables (`magiskinit` and `magiskboot`) for smaller sizes
|
||||
- [Core] Remove unnecessary mirror for magic mount
|
||||
- [Core] Update boot image detection logic to support more devices
|
||||
- [MagiskInit] Rewrite 2SI logic for injecting `magiskinit` as `init`
|
||||
- [MagiskInit] Update preinit partition detection
|
||||
- [Zygisk] Update internal JNI hooking implementation
|
||||
- [MagiskPolicy] Preserve sepolicy config flag after patching
|
||||
- [MagiskPolicy] Optimize patching rules to reduce the amount of new rules being injected
|
||||
- [DenyList] Support enforcing denylist when Zygisk is disabled
|
||||
- [Resetprop] Improve implementation to workaround several property modification detections
|
||||
- [Resetprop] Update to properly work with property overlays
|
||||
- [App] Major internal code refactoring
|
||||
- [App] Support patching Samsung firmware with images larger than 8GiB
|
||||
- [App] Use user-initiated job instead of foreground services on Android 14
|
||||
- [App] Support Android 13+ built-in per-app language preferences
|
||||
- [App] Add `action.sh` support to allow modules to define an action triggered from UI
|
||||
- [MagiskBoot] Support spliting kernel images without decompression
|
||||
- [MagiskBoot] Properly support vendor boot images
|
||||
- [MagiskBoot] Disable Samsung PROCA from kernel image
|
||||
|
||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
||||
@@ -1,5 +1,7 @@
|
||||
# Release Notes
|
||||
|
||||
- [v28.1](28100.md)
|
||||
- [v28.0](28000.md)
|
||||
- [v27.0](27000.md)
|
||||
- [v26.4](26400.md)
|
||||
- [v26.3](26300.md)
|
||||
|
||||
@@ -30,5 +30,5 @@ android.nonFinalResIds=false
|
||||
|
||||
# Magisk
|
||||
magisk.stubVersion=40
|
||||
magisk.versionCode=27008
|
||||
magisk.versionCode=28100
|
||||
magisk.ondkVersion=r27.4
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
[versions]
|
||||
kotlin = "2.0.20"
|
||||
android = "8.6.0"
|
||||
ksp = "2.0.20-1.0.25"
|
||||
kotlin = "2.0.21"
|
||||
android = "8.7.3"
|
||||
ksp = "2.0.21-1.0.28"
|
||||
rikka = "1.3.0"
|
||||
navigation = "2.8.0"
|
||||
navigation = "2.8.4"
|
||||
libsu = "6.0.0"
|
||||
moshi = "1.15.1"
|
||||
okhttp = "4.12.0"
|
||||
@@ -11,7 +11,7 @@ retrofit = "2.11.0"
|
||||
room = "2.6.1"
|
||||
|
||||
[libraries]
|
||||
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.78.1" }
|
||||
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.79" }
|
||||
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.27.1" }
|
||||
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||
retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
|
||||
@@ -26,25 +26,25 @@ timber = { module = "com.jakewharton.timber:timber", version = "5.0.1" }
|
||||
jgit = { module = "org.eclipse.jgit:org.eclipse.jgit", version = "6.10.0.202406032230-r" }
|
||||
|
||||
# AndroidX
|
||||
activity = { module = "androidx.activity:activity", version = "1.9.2" }
|
||||
activity = { module = "androidx.activity:activity", version = "1.9.3" }
|
||||
appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.0" }
|
||||
core-ktx = { module = "androidx.core:core-ktx", version = "1.13.1" }
|
||||
core-ktx = { module = "androidx.core:core-ktx", version = "1.15.0" }
|
||||
core-splashscreen = { module = "androidx.core:core-splashscreen", version = "1.0.1" }
|
||||
constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.1.4" }
|
||||
fragment-ktx = { module = "androidx.fragment:fragment-ktx", version = "1.8.3" }
|
||||
constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.2.0" }
|
||||
fragment-ktx = { module = "androidx.fragment:fragment-ktx", version = "1.8.5" }
|
||||
navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation" }
|
||||
navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" }
|
||||
profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version = "1.3.1" }
|
||||
profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version = "1.4.1" }
|
||||
recyclerview = { module = "androidx.recyclerview:recyclerview", version = "1.3.2" }
|
||||
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
||||
room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
||||
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||
swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0" }
|
||||
transition = { module = "androidx.transition:transition", version = "1.5.1" }
|
||||
collection-ktx = { module = "androidx.collection:collection-ktx", version = "1.4.3" }
|
||||
lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version = "2.8.5" }
|
||||
collection-ktx = { module = "androidx.collection:collection-ktx", version = "1.4.5" }
|
||||
lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version = "2.8.7" }
|
||||
material = { module = "com.google.android.material:material", version = "1.12.0" }
|
||||
jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.2" }
|
||||
jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.3" }
|
||||
|
||||
# topjohnwu
|
||||
indeterminate-checkbox = { module = "com.github.topjohnwu:indeterminate-checkbox", version = "1.0.7" }
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user