1
mirror of https://github.com/topjohnwu/Magisk synced 2025-11-09 00:32:30 +01:00

Compare commits

..

27 Commits
v30.1 ... v30.2

Author SHA1 Message Date
topjohnwu
975120d6a6 Release Magisk v30.2
[skip ci]
2025-08-06 03:32:32 -07:00
topjohnwu
e489b3b6dd Migrate load_modules to Rust 2025-08-05 11:24:55 -07:00
topjohnwu
589a270b8d Migrate disable/remove modules to Rust 2025-08-05 11:24:55 -07:00
topjohnwu
7961be5cfa Migrate prepare_modules to Rust 2025-08-05 11:24:55 -07:00
topjohnwu
959430e030 Fix systemless hosts installation 2025-08-05 09:44:51 -07:00
topjohnwu
2923c8ccd1 Add module upgrade test 2025-08-05 09:44:51 -07:00
topjohnwu
7df4a9d74f Add uninstaller.sh test 2025-08-05 09:44:51 -07:00
topjohnwu
bf4ed295da Update cargo dependencies 2025-08-02 13:43:27 -07:00
topjohnwu
a5fca960dc Update gradle and dependencies 2025-08-02 02:29:14 -07:00
topjohnwu
f99912b9db Update libsystem_properties 2025-07-21 13:47:30 -07:00
5ec1cff
a54bdb54e4 Skip avb 1,0 verify if tail contains avb 2.0 header
This way, magiskboot will not print "unexpected ASN.1 DER tag: expected SEQUENCE, got APPLICATION [1] (primitive)".
2025-07-21 00:51:14 -07:00
topjohnwu
cd9851a1fe Add regression test for #9179 2025-07-18 17:58:29 -07:00
Wang Han
9ca469898c Use worker for replace feature
This fixes https://github.com/topjohnwu/Magisk/issues/9179.
2025-07-18 16:57:20 -07:00
𝗛𝗼𝗹𝗶
0665549473 Update Turkish
Missing parts were filled in and made better
2025-07-14 10:46:05 -07:00
topjohnwu
9d7a14b335 Remove unnecessary return 2025-07-14 10:03:22 -07:00
Wang Han
62e29fee74 Treat bind mount failure same as C++ implementation
This fixes #9139 and #9174.
2025-07-14 00:27:24 -07:00
igor
e472db552b Update portuguese/english translations 2025-07-11 10:52:21 -07:00
topjohnwu
466e4bd4e1 Update cargo dependencies 2025-07-11 02:04:33 -07:00
topjohnwu
4cf525c588 Add Android canary builds into CI tests 2025-07-11 00:16:39 -07:00
topjohnwu
c8aec2510d Restrict sccache cache size 2025-07-11 00:16:39 -07:00
topjohnwu
ccbfe0e66e Update gradle dependencies 2025-07-10 15:55:14 -07:00
南宫雪珊
23ea28de6f scripts: fix modules_update dir context 2025-07-10 10:59:39 -07:00
topjohnwu
55c3ee3a6f Move Zygisk code out of module.cpp 2025-07-07 13:43:11 -07:00
vvb2060
2a42ca2b8f app: fix time i18n 2025-07-07 11:04:18 -07:00
topjohnwu
a897e82fa4 Remove release notes
They are embedded into GitHub releases
2025-07-07 10:37:45 -07:00
topjohnwu
ffa15831d3 Add release dates 2025-07-07 10:35:22 -07:00
topjohnwu
a344ebf28c Add v30.1 changelog 2025-07-03 18:02:27 -07:00
88 changed files with 822 additions and 1398 deletions

View File

@@ -45,7 +45,7 @@ runs:
env:
SCCACHE_DIRECT: false
SCCACHE_DIR: ${{ github.workspace }}/.sccache
SCCACHE_CACHE_SIZE: 2G
SCCACHE_CACHE_SIZE: ${{ inputs.is-asset-build == 'true' && '2G' || '300M' }}
SCCACHE_IDLE_TIMEOUT: 0
run: |
bash $GITHUB_ACTION_PATH/sccache.sh

View File

@@ -82,12 +82,10 @@ jobs:
strategy:
fail-fast: false
matrix:
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, "36.0-CANARY"]
type: [""]
include:
- version: 36
type: "google_apis"
- version: 36
- version: "36.0-CANARY"
type: "google_apis_ps16k"
steps:

View File

@@ -22,11 +22,11 @@ import com.topjohnwu.magisk.core.ktx.activity
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.AppMigration
import com.topjohnwu.magisk.core.utils.LocaleSetting
import com.topjohnwu.magisk.core.utils.RootUtils
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.events.AddHomeIconEvent
import com.topjohnwu.magisk.events.AuthEvent
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch
class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
@@ -130,7 +130,8 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
}
private fun createHosts() {
Shell.cmd("add_hosts_module").submit {
viewModelScope.launch {
RootUtils.addSystemlessHosts()
AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
}
}

View File

@@ -18,12 +18,6 @@ gradlePlugin {
}
}
kotlin {
compilerOptions {
languageVersion = KotlinVersion.KOTLIN_2_0
}
}
dependencies {
implementation(kotlin("gradle-plugin", libs.versions.kotlin.get()))
implementation(libs.android.gradle.plugin)

View File

@@ -309,9 +309,9 @@ fun Project.setupStubApk() {
outputs.dir(outResDir)
doLast {
val apkTmp = File("${apk}.tmp")
exec {
providers.exec {
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
}
}.result.get()
val bos = ByteArrayOutputStream()
ZipFile(apkTmp).use { src ->

View File

@@ -27,10 +27,15 @@ android {
aidl = true
buildConfig = true
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
api(project(":shared"))
coreLibraryDesugaring(libs.jdk.libs)
api(libs.timber)
api(libs.markwon.core)

View File

@@ -38,3 +38,4 @@
-allowaccessmodification
-dontwarn org.junit.**
-dontwarn org.apache.**

View File

@@ -6,4 +6,5 @@ package com.topjohnwu.magisk.core.utils;
interface IRootUtils {
android.app.ActivityManager.RunningAppProcessInfo getAppProcess(int pid);
IBinder getFileSystem();
boolean addSystemlessHosts();
}

View File

@@ -109,7 +109,7 @@ fun PackageManager.getPackageInfo(uid: Int, pid: Int): PackageInfo? {
return null
}
// Try to find package name from PID
val proc = RootUtils.obj?.getAppProcess(pid)
val proc = RootUtils.getAppProcess(pid)
if (proc == null) {
if (uid == Process.SHELL_UID) {
// It is possible that some apps installed are sharing UID with shell.

View File

@@ -14,10 +14,11 @@ import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.lang.reflect.Field
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.Collections
import java.util.Locale
inline fun <In : Closeable, Out : Closeable> withInOut(
input: In,
@@ -83,19 +84,15 @@ inline fun <T, R> Flow<T>.concurrentMap(crossinline transform: suspend (T) -> R)
}
}
fun Long.toTime(format: DateFormat) = format.format(this).orEmpty()
fun Long.toTime(format: DateTimeFormatter): String = format.format(Instant.ofEpochMilli(this))
// Some devices don't allow filenames containing ":"
val timeFormatStandard by lazy {
SimpleDateFormat(
"yyyy-MM-dd'T'HH.mm.ss",
Locale.ROOT
)
val timeFormatStandard: DateTimeFormatter by lazy {
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH.mm.ss").withZone(ZoneId.systemDefault())
}
val timeDateFormat: DateFormat by lazy {
DateFormat.getDateTimeInstance(
DateFormat.DEFAULT,
DateFormat.DEFAULT,
Locale.ROOT
)
val timeDateFormat: DateTimeFormatter by lazy {
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.systemDefault())
}
val dateFormat: DateTimeFormatter by lazy {
DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withZone(ZoneId.systemDefault())
}

View File

@@ -7,8 +7,7 @@ import com.squareup.moshi.JsonClass
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.ToJson
import kotlinx.parcelize.Parcelize
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME
import java.time.Instant
@JsonClass(generateAdapter = true)
class UpdateJson(
@@ -40,13 +39,13 @@ data class ReleaseAssets(
class DateTimeAdapter {
@ToJson
fun toJson(date: LocalDateTime): String {
fun toJson(date: Instant): String {
return date.toString()
}
@FromJson
fun fromJson(date: String): LocalDateTime {
return LocalDateTime.parse(date, ISO_OFFSET_DATE_TIME)
fun fromJson(date: String): Instant {
return Instant.parse(date)
}
}
@@ -57,7 +56,7 @@ data class Release(
val prerelease: Boolean,
val assets: List<ReleaseAssets>,
val body: String,
@Json(name = "created_at") val createdTime: LocalDateTime,
@Json(name = "created_at") val createdTime: Instant,
) {
val versionCode: Int get() {
return if (tag[0] == 'v') {

View File

@@ -13,7 +13,7 @@ import java.io.IOException
import java.util.Locale
data class LocalModule(
private val base: ExtendedFile,
val base: ExtendedFile,
) : Module() {
private val svc get() = ServiceLocator.networkService

View File

@@ -10,13 +10,13 @@ import com.topjohnwu.magisk.core.Config.Value.STABLE_CHANNEL
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.data.GithubApiServices
import com.topjohnwu.magisk.core.data.RawUrl
import com.topjohnwu.magisk.core.ktx.dateFormat
import com.topjohnwu.magisk.core.model.Release
import com.topjohnwu.magisk.core.model.ReleaseAssets
import com.topjohnwu.magisk.core.model.UpdateInfo
import retrofit2.HttpException
import timber.log.Timber
import java.io.IOException
import java.time.format.DateTimeFormatter
class NetworkService(
private val raw: RawUrl,
@@ -74,7 +74,7 @@ class NetworkService(
private inline fun Release.asPublicInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
val version = tag.drop(1)
val date = createdTime.format(DateTimeFormatter.ofPattern("yyyy.M.d"))
val date = dateFormat.format(createdTime)
return UpdateInfo(
version = version,
versionCode = versionCode,

View File

@@ -7,11 +7,14 @@ import android.content.ServiceConnection
import android.os.IBinder
import android.system.Os
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
import com.topjohnwu.superuser.ipc.RootService
import com.topjohnwu.superuser.nio.FileSystemManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.File
import java.util.concurrent.locks.AbstractQueuedSynchronizer
@@ -43,16 +46,7 @@ class RootUtils(stub: Any?) : RootService() {
return object : IRootUtils.Stub() {
override fun getAppProcess(pid: Int) = safe(null) { getAppProcessImpl(pid) }
override fun getFileSystem(): IBinder = FileSystemManager.getService()
}
}
private inline fun <T> safe(default: T, block: () -> T): T {
return try {
block()
} catch (e: Throwable) {
// The process died unexpectedly
Timber.e(e)
default
override fun addSystemlessHosts() = safe(false) { addSystemlessHostsImpl() }
}
}
@@ -78,6 +72,26 @@ class RootUtils(stub: Any?) : RootService() {
return null
}
private fun addSystemlessHostsImpl(): Boolean {
val module = File(Const.MODULE_PATH, "hosts")
if (module.exists()) return true
val hosts = File(module, "system/etc/hosts")
if (!hosts.parentFile.mkdirs()) return false
File(module, "module.prop").outputStream().writer().use {
it.write("""
id=hosts
name=Systemless Hosts
version=1.0
versionCode=1
author=Magisk
description=Magisk app built-in systemless hosts module
""".trimIndent())
}
File("/system/etc/hosts").copyTo(hosts)
File(module, "update").createNewFile()
return true
}
object Connection : AbstractQueuedSynchronizer(), ServiceConnection {
init {
state = 1
@@ -131,11 +145,25 @@ class RootUtils(stub: Any?) : RootService() {
return field
}
private set
var obj: IRootUtils? = null
private var obj: IRootUtils? = null
get() {
Connection.await()
return field
}
private set
fun getAppProcess(pid: Int) = safe(null) { obj?.getAppProcess(pid) }
suspend fun addSystemlessHosts() =
withContext(Dispatchers.IO) { safe(false) { obj?.addSystemlessHosts() ?: false } }
private inline fun <T> safe(default: T, block: () -> T): T {
return try {
block()
} catch (e: Throwable) {
// The process died unexpectedly
Timber.e(e)
default
}
}
}
}

View File

@@ -12,9 +12,11 @@ import com.topjohnwu.magisk.test.Environment.Companion.INVALID_ZYGISK
import com.topjohnwu.magisk.test.Environment.Companion.MOUNT_TEST
import com.topjohnwu.magisk.test.Environment.Companion.REMOVE_TEST
import com.topjohnwu.magisk.test.Environment.Companion.SEPOLICY_RULE
import com.topjohnwu.magisk.test.Environment.Companion.UPGRADE_TEST
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
@@ -55,7 +57,7 @@ class AdditionalTest : BaseTest {
@Test
fun testModuleCount() {
var expected = 3
var expected = 4
if (Environment.mount()) expected++
if (Environment.preinit()) expected++
if (Environment.lsposed()) expected++
@@ -98,9 +100,10 @@ class AdditionalTest : BaseTest {
RootUtils.fs.getFile("/system/bin/screenrecord").exists()
)
val egg = RootUtils.fs.getFile("/system/app/EasterEgg").list() ?: arrayOf()
assertTrue(
"/system/app/EasterEgg should be empty",
egg.isEmpty()
assertArrayEquals(
"/system/app/EasterEgg should be replaced",
egg,
arrayOf("newfile")
)
}
@@ -134,5 +137,25 @@ class AdditionalTest : BaseTest {
@Test
fun testRemoveModule() {
assertNull("$REMOVE_TEST should be removed", modules.find { it.id == REMOVE_TEST })
assertTrue(
"Uninstaller of $REMOVE_TEST should be run",
RootUtils.fs.getFile(Environment.REMOVE_TEST_MARKER).exists()
)
}
@Test
fun testModuleUpgrade() {
val module = modules.find { it.id == UPGRADE_TEST }
assertNotNull("$UPGRADE_TEST is not installed", module)
module!!
assertFalse("$UPGRADE_TEST should be disabled", module.enable)
assertTrue(
"$UPGRADE_TEST should be updated",
module.base.getChildFile("post-fs-data.sh").exists()
)
assertFalse(
"$UPGRADE_TEST should be updated",
module.base.getChildFile("service.sh").exists()
)
}
}

View File

@@ -58,12 +58,15 @@ class Environment : BaseTest {
return Build.VERSION.SDK_INT >= 27
}
private const val MODULE_UPDATE_PATH = "/data/adb/modules_update"
private const val MODULE_ERROR = "Module zip processing incorrect"
const val MOUNT_TEST = "mount_test"
const val SEPOLICY_RULE = "sepolicy_rule"
const val INVALID_ZYGISK = "invalid_zygisk"
const val REMOVE_TEST = "remove_test"
const val REMOVE_TEST_MARKER = "/dev/.remove_test_removed"
const val EMPTY_ZYGISK = "empty_zygisk"
const val UPGRADE_TEST = "upgrade_test"
}
object TimberLog : CallbackList<String>(Runnable::run) {
@@ -108,6 +111,9 @@ class Environment : BaseTest {
assertTrue(error, egg.mkdirs())
assertTrue(error, egg.getChildFile(".replace").createNewFile())
// Create /system/app/EasterEgg/newfile
assertTrue(error, egg.getChildFile("newfile").createNewFile())
// Delete /system/bin/screenrecord
val bin = path.getChildFile("system").getChildFile("bin")
assertTrue(error, bin.mkdirs())
@@ -117,7 +123,9 @@ class Environment : BaseTest {
}
private fun setupSystemlessHost() {
assertTrue("hosts setup failed", Shell.cmd("add_hosts_module").exec().isSuccess)
val error = "hosts setup failed"
assertTrue(error, runBlocking { RootUtils.addSystemlessHosts() })
assertTrue(error, RootUtils.fs.getFile(Const.MODULE_PATH).getChildFile("hosts").exists())
}
private fun setupSepolicyRuleModule(root: ExtendedFile) {
@@ -167,12 +175,39 @@ class Environment : BaseTest {
// Create a new module but mark is as "remove"
val module = LocalModule(path)
assertTrue(error, path.mkdirs())
// Create uninstaller script
path.getChildFile("uninstall.sh").newOutputStream().writer().use {
it.write("touch $REMOVE_TEST_MARKER")
}
assertTrue(error, path.getChildFile("service.sh").createNewFile())
module.remove = true
assertTrue(error, Shell.cmd("set_default_perm $path").exec().isSuccess)
}
private fun setupUpgradeModule(root: ExtendedFile, update: ExtendedFile) {
val error = "$UPGRADE_TEST setup failed"
val oldPath = root.getChildFile(UPGRADE_TEST)
val newPath = update.getChildFile(UPGRADE_TEST)
// Create an existing module but mark as "disable
val module = LocalModule(oldPath)
assertTrue(error, oldPath.mkdirs())
module.enable = false
// Install service.sh into the old module
assertTrue(error, oldPath.getChildFile("service.sh").createNewFile())
// Create an upgrade module
assertTrue(error, newPath.mkdirs())
// Install post-fs-data.sh into the new module
assertTrue(error, newPath.getChildFile("post-fs-data.sh").createNewFile())
assertTrue(error, Shell.cmd(
"set_default_perm $oldPath",
"set_default_perm $newPath",
).exec().isSuccess)
}
@Test
fun setupEnvironment() {
runBlocking {
@@ -217,12 +252,14 @@ class Environment : BaseTest {
}
val root = RootUtils.fs.getFile(Const.MODULE_PATH)
if (mount()) { setupMountTest(root) }
if (preinit()) { setupSepolicyRuleModule(root) }
val update = RootUtils.fs.getFile(MODULE_UPDATE_PATH)
if (mount()) { setupMountTest(update) }
if (preinit()) { setupSepolicyRuleModule(update) }
setupSystemlessHost()
setupEmptyZygiskModule(root)
setupInvalidZygiskModule(root)
setupEmptyZygiskModule(update)
setupInvalidZygiskModule(update)
setupRemoveModule(root)
setupUpgradeModule(root, update)
}
@Test

View File

@@ -53,6 +53,7 @@
<string name="touch_filtered_warning">Como um app está ocultando uma solicitação de SuperUsuário, o Magisk não pode verificar sua resposta.</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
<string name="restrict">Restringir</string>
<string name="grant">Permitir</string>
<string name="su_warning">Permite acesso total ao seu dispositivo.\nNão permita se você não tiver certeza do que está fazendo!</string>
<string name="forever">Sempre</string>
@@ -170,6 +171,8 @@
<string name="settings_su_auth_title">Autenticação de usuário</string>
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante solicitações de SuperUsuário</string>
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
<string name="settings_su_restrict_title">Restringir recursos root</string>
<string name="settings_su_restrict_summary">Restringirá novos apps de SuperUsuário por padrão. Aviso: isso quebrará a maioria dos apps. Não ative se você não souber o que está fazendo.</string>
<string name="settings_customization">Personalizações</string>
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
<string name="settings_doh_title">DNS sobre HTTPS</string>

View File

@@ -53,6 +53,7 @@
<string name="touch_filtered_warning">Como um app está a ocultar um pedido de SuperUsuário, o Magisk não consegue verificar a sua resposta.</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
<string name="restrict">Restringir</string>
<string name="grant">Permitir</string>
<string name="su_warning">Permite o acesso total ao seu dispositivo.\nNão o permita se não tiver a certeza do que está a fazer!</string>
<string name="forever">Sempre</string>
@@ -129,7 +130,7 @@
<string name="settings_restore_app_title">Restaurar app do Magisk</string>
<string name="settings_restore_app_summary">Desoculta o app do Magisk e restaura o APK original</string>
<string name="language">Idioma</string>
<string name="system_default">(Padrão do sistema)</string>
<string name="system_default">(Predefinição do sistema)</string>
<string name="settings_check_update_title">Verificar por atualizações</string>
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
<string name="settings_update_channel_title">Canal de atualização</string>
@@ -170,6 +171,8 @@
<string name="settings_su_auth_title">Autenticação de usuário</string>
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante pedidos de SuperUsuário</string>
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
<string name="settings_su_restrict_title">Restringir recursos root</string>
<string name="settings_su_restrict_summary">Restringirá novos apps de SuperUsuário por predefinição. Aviso: isto quebrará a maioria dos apps. Não ative se você não souber o que está a fazer.</string>
<string name="settings_customization">Personalizações</string>
<string name="setting_add_shortcut_summary">Adicione um atalho no ecrã inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
<string name="settings_doh_title">DNS sobre HTTPS</string>

File diff suppressed because it is too large Load Diff

View File

@@ -172,7 +172,7 @@
<string name="settings_su_auth_summary">Ask for user authentication during Superuser requests</string>
<string name="settings_su_auth_insecure">No authentication method is configured on the device</string>
<string name="settings_su_restrict_title">Restrict root capabilities</string>
<string name="settings_su_restrict_summary">Will restrict new superuser apps by default. Warning, this will break most apps, do not enable it.</string>
<string name="settings_su_restrict_summary">Will restrict new Superuser apps by default. Warning: this will break most apps. Don\'t enable it unless you know what you\'re doing.</string>
<string name="settings_customization">Customization</string>
<string name="setting_add_shortcut_summary">Add a pretty shortcut to the home screen in case the name and icon are difficult to recognize after hiding the app</string>
<string name="settings_doh_title">DNS over HTTPS</string>

View File

@@ -30,4 +30,4 @@ android.nonFinalResIds=false
# Magisk
magisk.stubVersion=40
magisk.versionCode=30100
magisk.versionCode=30200

View File

@@ -1,17 +1,17 @@
[versions]
kotlin = "2.1.21"
android = "8.11.0"
ksp = "2.1.21-2.0.1"
kotlin = "2.2.0"
android = "8.12.0"
ksp = "2.2.0-2.0.2"
rikka = "1.3.0"
navigation = "2.9.0"
navigation = "2.9.3"
libsu = "6.0.0"
okhttp = "4.12.0"
okhttp = "5.1.0"
retrofit = "3.0.0"
room = "2.7.2"
[libraries]
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.81" }
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.27.1" }
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.28.0" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
retrofit-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofit" }
@@ -41,9 +41,9 @@ transition = { module = "androidx.transition:transition", version = "1.6.0" }
collection-ktx = { module = "androidx.collection:collection-ktx", version = "1.5.0" }
material = { module = "com.google.android.material:material", version = "1.12.0" }
jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.5" }
test-runner = { module = "androidx.test:runner", version = "1.6.2" }
test-rules = { module = "androidx.test:rules", version = "1.6.1" }
test-junit = { module = "androidx.test.ext:junit", version = "1.2.1" }
test-runner = { module = "androidx.test:runner", version = "1.7.0" }
test-rules = { module = "androidx.test:rules", version = "1.7.0" }
test-junit = { module = "androidx.test.ext:junit", version = "1.3.0" }
test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.3.0" }
# topjohnwu
@@ -62,6 +62,6 @@ android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref
ksp-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
navigation-safe-args-plugin = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "navigation" }
lsparanoid-plugin = { module = "org.lsposed.lsparanoid:gradle-plugin", version = "0.6.0" }
moshi-plugin = { module = "dev.zacsweers.moshix:dev.zacsweers.moshix.gradle.plugin", version = "0.30.0" }
moshi-plugin = { module = "dev.zacsweers.moshix:dev.zacsweers.moshix.gradle.plugin", version = "0.31.0" }
[plugins]

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -2,7 +2,6 @@
- [Installation Instructions](install.md)
- [Frequently Asked Questions](faq.md)
- [Release Notes](releases/index.md)
- [Magisk Changelog](changes.md)
The following sections are for developers

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +0,0 @@
# 2019.2.4 Magisk v18.1
What is a better way to celebrate Chinese New Year than a new Magisk update!
### EMUI 9 Support
Welcome on board "again", Huawei! Even though Huawei had officially blocked bootloader unlocks, people still love to buy them (duh), and there are paid services that unlock Huawei bootloaders. So hey, get Magisk installed on that bad boy! One caveat is that since Huawei have changed the partitions, special workarounds has to be done. Details and instructions are in the newly created [instruction page](https://topjohnwu.github.io/Magisk/install.html)
### Support Down to Android 4.2
Because why not, it was quite a lot of fun LOL. All devices running KitKat and higher will have all features enabled. MagiskHide and resetprop aren't possible on Jellybean, and Magic Mount (modules) is temporarily disabled; basically it only works as a root solution for now. Android 4.1 isn't 100% usable yet, so installation is also temporarily blocked. Eventually, all Jellybean devices will have full Magic Mount and MagiskSU support.
### Major Magisk Manager Update
Aside from the obvious major UI overhaul, tons of little user experience and performance improvements are also added. The app is finally less crappy now :)
### Final Words
I'm aware that there are apps updated to detect Magisk, however no MagiskHide improvements efforts are done in this release; v18.1 is aimed to be as stable as possible. Stay tuned for future public betas, or if you are more adventurous, jump on the Canary Channel bandwagon for more aggressive hiding techniques :)
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +0,0 @@
# 2019.5.1 Magisk v19.1
Finally, a lovely stable release!
For those that were using v18.1, here are some quick highlights of v19.0
- Imageless Magisk: Although module migration was tested, there are still chances that your modules will get lost in the process. Be prepared to reinstall your existing modules in that case.
- Native 64-bit support
- Zygote Ptrace Based MagiskHide
Other than adding support for Samsung system-as-root devices, this release is mostly bug fixes from v19.0. Enjoy :)
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)

View File

@@ -1 +0,0 @@
# TODO

View File

@@ -1 +0,0 @@
# TODO

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More