mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 02:57:25 +00:00
Compare commits
19 Commits
canary-270
...
canary-270
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4f18a66d73 | ||
![]() |
250dc16007 | ||
![]() |
7af273e047 | ||
![]() |
e381aebaa0 | ||
![]() |
45d91c9658 | ||
![]() |
4a9158f667 | ||
![]() |
0d9ee89e7f | ||
![]() |
abaff72304 | ||
![]() |
b828e2d0b2 | ||
![]() |
53d7cbc11b | ||
![]() |
310be7ab47 | ||
![]() |
60894e458f | ||
![]() |
fbebb6ac10 | ||
![]() |
a9f8c20703 | ||
![]() |
ae0b15d197 | ||
![]() |
869aa62328 | ||
![]() |
dcd3bc58a3 | ||
![]() |
a82f17c594 | ||
![]() |
b38fd1ca5f |
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
@@ -10,7 +10,7 @@ runs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "17"
|
||||
java-version: "21"
|
||||
|
||||
- name: Set up Python 3
|
||||
uses: actions/setup-python@v5
|
||||
|
@@ -22,7 +22,7 @@ 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-27007)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-27008)
|
||||
|
||||
## Useful Links
|
||||
|
||||
|
@@ -13,7 +13,7 @@ kapt {
|
||||
useBuildCache = true
|
||||
mapDiagnosticLocations = true
|
||||
javacOptions {
|
||||
option("-Xmaxerrs", 1000)
|
||||
option("-Xmaxerrs", "1000")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,15 @@ android {
|
||||
buildFeatures {
|
||||
dataBinding = true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":app:core"))
|
||||
coreLibraryDesugaring(libs.jdk.libs)
|
||||
|
||||
implementation(libs.indeterminate.checkbox)
|
||||
implementation(libs.rikka.layoutinflater)
|
||||
|
@@ -0,0 +1,116 @@
|
||||
package com.topjohnwu.magisk.ui.module
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.core.view.isVisible
|
||||
import com.topjohnwu.magisk.R
|
||||
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 {
|
||||
|
||||
override val layoutRes = R.layout.fragment_action_md2
|
||||
override val viewModel by viewModel<ActionViewModel>()
|
||||
override val snackbarView: View get() = binding.snackbarContainer
|
||||
|
||||
private var defaultOrientation = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
viewModel.args = ActionFragmentArgs.fromBundle(requireArguments())
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity?.setTitle(viewModel.args.name)
|
||||
binding.closeBtn.setOnClickListener {
|
||||
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
|
||||
}
|
||||
)
|
||||
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 -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.menu_flash, menu)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(item: MenuItem): Boolean {
|
||||
return viewModel.onMenuItemClicked(item)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
defaultOrientation = activity?.requestedOrientation ?: -1
|
||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
if (savedInstanceState == null) {
|
||||
viewModel.startRunAction()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
override fun onDestroyView() {
|
||||
if (defaultOrientation != -1) {
|
||||
activity?.requestedOrientation = defaultOrientation
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onKeyEvent(event: KeyEvent): Boolean {
|
||||
return when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (viewModel.state.value == ActionViewModel.State.RUNNING) return true
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onPreBind(binding: FragmentActionMd2Binding) = Unit
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
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 kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ActionViewModel : BaseViewModel() {
|
||||
|
||||
enum class State {
|
||||
RUNNING, SUCCESS, FAILED
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
private val logItems = mutableListOf<String>().synchronized()
|
||||
private val outItems = object : CallbackList<String>() {
|
||||
override fun onAddElement(e: String?) {
|
||||
e ?: return
|
||||
items.add(ConsoleItem(e))
|
||||
logItems.add(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun startRunAction() {
|
||||
viewModelScope.launch {
|
||||
onResult(RunAction(args.id, outItems, logItems).exec())
|
||||
}
|
||||
}
|
||||
|
||||
private fun onResult(success: Boolean) {
|
||||
_state.value = if (success) State.SUCCESS else State.FAILED
|
||||
}
|
||||
|
||||
fun onMenuItemClicked(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_save -> savePressed()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun savePressed() = withExternalRW {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val name = "%s_action_log_%s.log".format(
|
||||
args.name,
|
||||
System.currentTimeMillis().toTime(timeFormatStandard)
|
||||
)
|
||||
val file = MediaStoreUtils.getFile(name)
|
||||
file.uri.outputStream().bufferedWriter().use { writer ->
|
||||
synchronized(logItems) {
|
||||
logItems.forEach {
|
||||
writer.write(it)
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
SnackbarEvent(file.toString()).publish()
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,6 +25,7 @@ class LocalModuleRvItem(
|
||||
override val layoutRes = R.layout.item_module_md2
|
||||
|
||||
val showNotice: Boolean
|
||||
val showAction: Boolean
|
||||
val noticeText: TextHolder
|
||||
|
||||
init {
|
||||
@@ -35,6 +36,7 @@ class LocalModuleRvItem(
|
||||
showNotice = zygiskUnloaded ||
|
||||
(Info.isZygiskEnabled && isRiru) ||
|
||||
(!Info.isZygiskEnabled && isZygisk)
|
||||
showAction = item.hasAction && !showNotice
|
||||
noticeText =
|
||||
when {
|
||||
zygiskUnloaded -> CoreR.string.zygisk_module_unloaded.asText()
|
||||
|
@@ -4,8 +4,10 @@ import android.net.Uri
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.MainDirections
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||
@@ -96,6 +98,10 @@ class ModuleViewModel : AsyncLoadViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun runAction(id: String, name: String) {
|
||||
MainDirections.actionActionFragment(id, name).navigate()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val uri = MutableLiveData<Uri?>()
|
||||
}
|
||||
|
@@ -78,8 +78,8 @@ class SuperuserViewModel(
|
||||
this@SuperuserViewModel, policy,
|
||||
info.packageName,
|
||||
info.sharedUserId != null,
|
||||
info.applicationInfo.loadIcon(pm),
|
||||
info.applicationInfo.getLabel(pm)
|
||||
info.applicationInfo?.loadIcon(pm) ?: pm.defaultActivityIcon,
|
||||
info.applicationInfo?.getLabel(pm) ?: info.packageName
|
||||
)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
null
|
||||
|
@@ -111,7 +111,7 @@ class SuRequestViewModel(
|
||||
// shared UID. We have no way to know where this request comes from.
|
||||
icon = pm.defaultActivityIcon
|
||||
title = "[SharedUID] ${info.sharedUserId}"
|
||||
packageName = info.sharedUserId
|
||||
packageName = info.sharedUserId.toString()
|
||||
} else {
|
||||
val prefix = if (info.sharedUserId == null) "" else "[SharedUID] "
|
||||
icon = app.loadIcon(pm)
|
||||
|
5
app/apk/src/main/res/drawable/ic_action_md2.xml
Normal file
5
app/apk/src/main/res/drawable/ic_action_md2.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
|
||||
|
||||
</vector>
|
68
app/apk/src/main/res/layout/fragment_action_md2.xml
Normal file
68
app/apk/src/main/res/layout/fragment_action_md2.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.topjohnwu.magisk.ui.module.ActionViewModel" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/internal_action_bar_size"
|
||||
app:layout_fitsSystemWindowsInsets="top"
|
||||
tools:layout_marginTop="@dimen/internal_action_bar_size">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/flash_content"
|
||||
scrollToLast="@{true}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
app:fitsSystemWindowsInsets="start|end|bottom"
|
||||
app:items="@{viewModel.items}"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:listitem="@layout/item_console_md2" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/close_btn"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/l1"
|
||||
android:layout_marginBottom="@dimen/l1"
|
||||
android:clickable="true"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:text="@string/close"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?colorOnPrimary"
|
||||
android:textStyle="bold"
|
||||
app:backgroundTint="?colorPrimary"
|
||||
app:icon="@drawable/ic_close_md2"
|
||||
app:iconTint="?colorOnPrimary"
|
||||
app:layout_fitsSystemWindowsInsets="bottom" />
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/snackbar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:fitsSystemWindowsInsets="top|bottom" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
@@ -189,12 +189,32 @@
|
||||
android:textColor="?colorError"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/module_remove"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_bar_barrier"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/module_config"
|
||||
app:layout_constraintTop_toTopOf="@+id/module_remove"
|
||||
tools:lines="2"
|
||||
tools:text="@tools:sample/lorem/random"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/module_config"
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
goneUnless="@{item.showAction}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:enabled="@{item.enabled}"
|
||||
android:focusable="true"
|
||||
android:onClick="@{() -> viewModel.runAction(item.item.id, item.item.name)}"
|
||||
android:text="@string/module_action"
|
||||
android:textAllCaps="false"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_action_md2"
|
||||
app:iconGravity="textStart"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/module_remove"
|
||||
app:layout_constraintTop_toTopOf="@+id/module_remove"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:srcCompat="@drawable/ic_download_md2" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
@@ -53,6 +53,21 @@
|
||||
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/actionFragment"
|
||||
android:name="com.topjohnwu.magisk.ui.module.ActionFragment"
|
||||
android:label="ActionFragment"
|
||||
tools:layout="@layout/fragment_action_md2" >
|
||||
|
||||
<argument
|
||||
android:name="id"
|
||||
app:argType="string" />
|
||||
|
||||
<argument
|
||||
android:name="name"
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/installFragment"
|
||||
android:name="com.topjohnwu.magisk.ui.install.InstallFragment"
|
||||
@@ -152,4 +167,12 @@
|
||||
app:popEnterAnim="@anim/fragment_enter_pop"
|
||||
app:popExitAnim="@anim/fragment_exit_pop" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_actionFragment"
|
||||
app:destination="@id/actionFragment"
|
||||
app:enterAnim="@anim/fragment_enter"
|
||||
app:exitAnim="@anim/fragment_exit"
|
||||
app:popEnterAnim="@anim/fragment_enter_pop"
|
||||
app:popExitAnim="@anim/fragment_exit_pop" />
|
||||
|
||||
</navigation>
|
||||
|
@@ -37,6 +37,7 @@ data class LocalModule(
|
||||
val isRiru: Boolean get() = (id == "riru-core") || riruFolder.exists()
|
||||
val isZygisk: Boolean get() = zygiskFolder.exists()
|
||||
val zygiskUnloaded: Boolean get() = unloaded.exists()
|
||||
val hasAction: Boolean;
|
||||
|
||||
var enable: Boolean
|
||||
get() = !disableFile.exists()
|
||||
@@ -100,6 +101,8 @@ data class LocalModule(
|
||||
if (name.isEmpty()) {
|
||||
name = id
|
||||
}
|
||||
|
||||
hasAction = RootUtils.fs.getFile(path, "action.sh").exists()
|
||||
}
|
||||
|
||||
suspend fun fetch(): Boolean {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.topjohnwu.magisk.core.model.su
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
@@ -24,7 +24,7 @@ class SuLog(
|
||||
}
|
||||
|
||||
fun PackageManager.createSuLog(
|
||||
info: PackageInfo,
|
||||
info: ApplicationInfo,
|
||||
toUid: Int,
|
||||
fromPid: Int,
|
||||
command: String,
|
||||
@@ -33,13 +33,12 @@ fun PackageManager.createSuLog(
|
||||
context: String,
|
||||
gids: String,
|
||||
): SuLog {
|
||||
val appInfo = info.applicationInfo
|
||||
return SuLog(
|
||||
fromUid = appInfo.uid,
|
||||
fromUid = info.uid,
|
||||
toUid = toUid,
|
||||
fromPid = fromPid,
|
||||
packageName = getNameForUid(appInfo.uid)!!,
|
||||
appName = appInfo.getLabel(this),
|
||||
packageName = getNameForUid(info.uid)!!,
|
||||
appName = info.getLabel(this),
|
||||
command = command,
|
||||
action = policy,
|
||||
target = target,
|
||||
|
@@ -64,7 +64,7 @@ object SuCallbackHandler {
|
||||
val pm = context.packageManager
|
||||
|
||||
val log = runCatching {
|
||||
pm.getPackageInfo(fromUid, pid)?.let {
|
||||
pm.getPackageInfo(fromUid, pid)?.applicationInfo?.let {
|
||||
pm.createSuLog(it, toUid, pid, command, policy, target, seContext, gids)
|
||||
}
|
||||
}.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy, target, seContext, gids)
|
||||
|
@@ -125,8 +125,9 @@ object AppMigration {
|
||||
apk: File, out: OutputStream,
|
||||
pkg: String, label: CharSequence
|
||||
): Boolean {
|
||||
val info = context.packageManager.getPackageArchiveInfo(apk.path, 0) ?: return false
|
||||
val origLabel = info.applicationInfo.nonLocalizedLabel.toString()
|
||||
val pm = context.packageManager
|
||||
val info = pm.getPackageArchiveInfo(apk.path, 0)?.applicationInfo ?: return false
|
||||
val origLabel = info.nonLocalizedLabel.toString()
|
||||
try {
|
||||
JarMap.open(apk, true).use { jar ->
|
||||
val je = jar.getJarEntry(ANDROID_MANIFEST)
|
||||
|
@@ -0,0 +1,42 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
@@ -105,6 +105,7 @@
|
||||
<string name="reboot_safe_mode">Modo de segurança</string>
|
||||
<string name="module_version_author">%1$s por %2$s</string>
|
||||
<string name="module_state_remove">Remover</string>
|
||||
<string name="module_action">Ação</string>
|
||||
<string name="module_state_restore">Restaurar</string>
|
||||
<string name="module_action_install_external">Instalar a partir do armazenamento</string>
|
||||
<string name="update_available">Atualização disponível</string>
|
||||
@@ -173,7 +174,7 @@
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
|
||||
<string name="settings_random_name_title">Randomizar nome de saída</string>
|
||||
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar para evitar a detecção</string>
|
||||
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar (*.tar) para evitar a detecção</string>
|
||||
<string name="multiuser_mode">Modo multiusuário</string>
|
||||
<string name="settings_owner_only">Somente proprietário do dispositivo</string>
|
||||
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
|
||||
@@ -205,9 +206,12 @@
|
||||
<string name="repo_install_title">Instalar %1$s %2$s(%3$d)</string>
|
||||
<string name="download">Baixar</string>
|
||||
<string name="reboot">Reiniciar</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="release_notes">Notas da atualização</string>
|
||||
<string name="flashing">Flashando…</string>
|
||||
<string name="running">Executando…</string>
|
||||
<string name="done">Concluído!</string>
|
||||
<string name="done_action">Ação de execução de %1$s concluída</string>
|
||||
<string name="failure">Falhou!</string>
|
||||
<string name="hide_app_title">Ocultando o app do Magisk…</string>
|
||||
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>
|
||||
|
@@ -105,6 +105,7 @@
|
||||
<string name="reboot_safe_mode">Modo de segurança</string>
|
||||
<string name="module_version_author">%1$s por %2$s</string>
|
||||
<string name="module_state_remove">Remover</string>
|
||||
<string name="module_action">Ação</string>
|
||||
<string name="module_state_restore">Restaurar</string>
|
||||
<string name="module_action_install_external">Instalar a partir do armazenamento</string>
|
||||
<string name="update_available">Atualização disponível</string>
|
||||
@@ -173,7 +174,7 @@
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
|
||||
<string name="settings_random_name_title">Randomizar nome de saída</string>
|
||||
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar para evitar a detecção</string>
|
||||
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar (*.tar) para evitar a detecção</string>
|
||||
<string name="multiuser_mode">Modo multiusuário</string>
|
||||
<string name="settings_owner_only">Somente proprietário do dispositivo</string>
|
||||
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
|
||||
@@ -205,9 +206,12 @@
|
||||
<string name="repo_install_title">Instalar %1$s %2$s(%3$d)</string>
|
||||
<string name="download">Baixar</string>
|
||||
<string name="reboot">Reiniciar</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="release_notes">Notas da atualização</string>
|
||||
<string name="flashing">Flashando…</string>
|
||||
<string name="running">Executando…</string>
|
||||
<string name="done">Concluído!</string>
|
||||
<string name="done_action">Ação de execução de %1$s concluída</string>
|
||||
<string name="failure">Falhou!</string>
|
||||
<string name="hide_app_title">Ocultando o app do Magisk…</string>
|
||||
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>
|
||||
|
@@ -74,7 +74,6 @@
|
||||
<string name="su_revoke_msg">Konfirmo për të hequr të drejtat e %1$s?</string>
|
||||
<string name="toast">Dolli</string>
|
||||
<string name="none">Asnjë</string>
|
||||
|
||||
<string name="superuser_toggle_notification">Njoftimet</string>
|
||||
<string name="superuser_toggle_revoke">Të drejtat</string>
|
||||
<string name="superuser_policy_none">Asnjë aplikacion nuk ka kërkuar akoma akses për super-përdoruesin.</string>
|
||||
@@ -91,8 +90,6 @@
|
||||
<string name="selinux_context">Konteksti SELinux: %s</string>
|
||||
<string name="supp_group">Grupi suplementar: %s</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
|
||||
<!--MagiskHide-->
|
||||
<string name="show_system_app">Shfaq aplikacionet e sistemit</string>
|
||||
<string name="show_os_app">Shfaq aplikacionet e sistemit operativ</string>
|
||||
@@ -109,6 +106,7 @@
|
||||
<string name="reboot_safe_mode">Rinis në safe mode</string>
|
||||
<string name="module_version_author">%1$s nga %2$s</string>
|
||||
<string name="module_state_remove">Hiqe</string>
|
||||
<string name="module_action">Veprim</string>
|
||||
<string name="module_state_restore">Rikëthe</string>
|
||||
<string name="module_action_install_external">Instaloni nga sdcard</string>
|
||||
<string name="update_available">Përditësimi në dispozicion</string>
|
||||
@@ -207,9 +205,12 @@
|
||||
<string name="repo_install_title">Instalo %1$s %2$s(%3$d)</string>
|
||||
<string name="download">Shkarko</string>
|
||||
<string name="reboot">Rinis</string>
|
||||
<string name="close">Mbylle</string>
|
||||
<string name="release_notes">Shënimet e lëshimit</string>
|
||||
<string name="flashing">Duke flashuar…</string>
|
||||
<string name="running">Duke vepruar...</string>
|
||||
<string name="done">U krye!</string>
|
||||
<string name="done_action">Veprimi i ekzekutimit të %1$s u krye</string>
|
||||
<string name="failure">Dështoi!</string>
|
||||
<string name="hide_app_title">Fshehja e aplikacionit Magisk…</string>
|
||||
<string name="open_link_failed_toast">Nuk u gjet asnjë aplikacion për të hapur lidhjen</string>
|
||||
|
@@ -109,6 +109,7 @@
|
||||
<string name="reboot_safe_mode">Safe mode</string>
|
||||
<string name="module_version_author">%1$s by %2$s</string>
|
||||
<string name="module_state_remove">Remove</string>
|
||||
<string name="module_action">Action</string>
|
||||
<string name="module_state_restore">Restore</string>
|
||||
<string name="module_action_install_external">Install from storage</string>
|
||||
<string name="update_available">Update Available</string>
|
||||
@@ -211,9 +212,12 @@
|
||||
<string name="repo_install_title">Install %1$s %2$s(%3$d)</string>
|
||||
<string name="download">Download</string>
|
||||
<string name="reboot">Reboot</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="release_notes">Release notes</string>
|
||||
<string name="flashing">Flashing…</string>
|
||||
<string name="running">Running…</string>
|
||||
<string name="done">Done!</string>
|
||||
<string name="done_action">Done running action of %1$s</string>
|
||||
<string name="failure">Failed!</string>
|
||||
<string name="hide_app_title">Hiding the Magisk app…</string>
|
||||
<string name="open_link_failed_toast">No app found to open the link</string>
|
||||
|
@@ -69,7 +69,7 @@ private val Project.androidComponents
|
||||
|
||||
fun Project.setupCommon() {
|
||||
androidBase {
|
||||
compileSdkVersion(34)
|
||||
compileSdkVersion(35)
|
||||
buildToolsVersion = "34.0.0"
|
||||
ndkPath = "$sdkDirectory/ndk/magisk"
|
||||
ndkVersion = "27.0.12077973"
|
||||
@@ -79,8 +79,8 @@ fun Project.setupCommon() {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
@@ -108,7 +108,7 @@ fun Project.setupCommon() {
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
compilerOptions {
|
||||
jvmTarget = JvmTarget.JVM_17
|
||||
jvmTarget = JvmTarget.JVM_21
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,7 +296,7 @@ fun Project.setupAppCommon() {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
targetSdk = 34
|
||||
targetSdk = 35
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -375,8 +375,8 @@ fun Project.setupStub() {
|
||||
val outAppClassDir = layout.buildDirectory.file("generated/source/app/${variantLowered}").get().asFile
|
||||
val outResDir = layout.buildDirectory.dir("generated/source/res/${variantLowered}").get().asFile
|
||||
val aapt = File(androidApp.sdkDirectory, "build-tools/${androidApp.buildToolsVersion}/aapt2")
|
||||
val apk = layout.buildDirectory.file("intermediates/processed_res/" +
|
||||
"${variantLowered}/process${variantCapped}Resources/out/resources-${variantLowered}.ap_").get().asFile
|
||||
val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
|
||||
"${variantLowered}/process${variantCapped}Resources/linked-resources-binary-format-${variantLowered}.ap_").get().asFile
|
||||
|
||||
val genManifestTask = tasks.register("generate${variantCapped}ObfuscatedClass") {
|
||||
inputs.property("seed", RAND_SEED)
|
||||
@@ -417,8 +417,8 @@ fun Project.setupStub() {
|
||||
registerJavaGeneratingTask(processResourcesTask, outResDir)
|
||||
}
|
||||
// Override optimizeReleaseResources task
|
||||
val apk = layout.buildDirectory.file("intermediates/processed_res/" +
|
||||
"release/processReleaseResources/out/resources-release.ap_").get().asFile
|
||||
val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
|
||||
"release/processReleaseResources/linked-resources-binary-format-release.ap_").get().asFile
|
||||
val optRes = layout.buildDirectory.file("intermediates/optimized_processed_res/" +
|
||||
"release/optimizeReleaseResources/resources-release-optimize.ap_").get().asFile
|
||||
afterEvaluate {
|
||||
|
@@ -54,6 +54,7 @@ A Magisk module is a folder placed in `/data/adb/modules` with the structure bel
|
||||
│ ├── post-fs-data.sh <--- This script will be executed in post-fs-data
|
||||
│ ├── service.sh <--- This script will be executed in late_start service
|
||||
| ├── uninstall.sh <--- This script will be executed when Magisk removes your module
|
||||
| ├── action.sh <--- This script will be executed when user click the action button in Magisk app
|
||||
│ ├── system.prop <--- Properties in this file will be loaded as system properties by resetprop
|
||||
│ ├── sepolicy.rule <--- Additional custom sepolicy rules
|
||||
│ │
|
||||
@@ -231,7 +232,7 @@ The list above will result in the following files being created: `$MODPATH/syste
|
||||
In Magisk, you can run boot scripts in 2 different modes: **post-fs-data** and **late_start service** mode.
|
||||
|
||||
- post-fs-data mode
|
||||
- This stage is BLOCKING. The boot process is paused before execution is done, or 10 seconds have passed.
|
||||
- This stage is BLOCKING. The boot process is paused before execution is done, or 40 seconds have passed.
|
||||
- Scripts run before any modules are mounted. This allows a module developer to dynamically adjust their modules before it gets mounted.
|
||||
- This stage happens before Zygote is started, which pretty much means everything in Android
|
||||
- **WARNING:** using `setprop` will deadlock the boot process! Please use `resetprop -n <prop_name> <prop_value>` instead.
|
||||
|
@@ -41,7 +41,9 @@ Supported actions:
|
||||
|
||||
repack [-n] <origbootimg> [outbootimg]
|
||||
Repack boot image components using files from the current directory
|
||||
to [outbootimg], or 'new-boot.img' if not specified.
|
||||
to [outbootimg], or 'new-boot.img' if not specified. Current directory
|
||||
should only contain required files for [outbootimg], or incorrect
|
||||
[outbootimg] may be produced.
|
||||
<origbootimg> is the original boot image used to unpack the components.
|
||||
By default, each component will be automatically compressed using its
|
||||
corresponding format detected in <origbootimg>. If a component file
|
||||
|
@@ -30,5 +30,5 @@ android.nonFinalResIds=false
|
||||
|
||||
# Magisk
|
||||
magisk.stubVersion=40
|
||||
magisk.versionCode=27007
|
||||
magisk.versionCode=27008
|
||||
magisk.ondkVersion=r27.4
|
||||
|
@@ -1,9 +1,9 @@
|
||||
[versions]
|
||||
kotlin = "2.0.10"
|
||||
android = "8.5.2"
|
||||
ksp = "2.0.10-1.0.24"
|
||||
kotlin = "2.0.20"
|
||||
android = "8.6.0"
|
||||
ksp = "2.0.20-1.0.25"
|
||||
rikka = "1.3.0"
|
||||
navigation = "2.7.7"
|
||||
navigation = "2.8.0"
|
||||
libsu = "6.0.0"
|
||||
moshi = "1.15.1"
|
||||
okhttp = "4.12.0"
|
||||
@@ -12,7 +12,7 @@ room = "2.6.1"
|
||||
|
||||
[libraries]
|
||||
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.78.1" }
|
||||
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.27.0" }
|
||||
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" }
|
||||
retrofit-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofit" }
|
||||
@@ -26,12 +26,12 @@ 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.1" }
|
||||
activity = { module = "androidx.activity:activity", version = "1.9.2" }
|
||||
appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.0" }
|
||||
core-ktx = { module = "androidx.core:core-ktx", version = "1.13.1" }
|
||||
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.2" }
|
||||
fragment-ktx = { module = "androidx.fragment:fragment-ktx", version = "1.8.3" }
|
||||
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" }
|
||||
@@ -42,8 +42,9 @@ 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.4" }
|
||||
lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version = "2.8.5" }
|
||||
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" }
|
||||
|
||||
# topjohnwu
|
||||
indeterminate-checkbox = { module = "com.github.topjohnwu:indeterminate-checkbox", version = "1.0.7" }
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
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.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
@@ -48,7 +48,9 @@ Supported actions:
|
||||
|
||||
repack [-n] <origbootimg> [outbootimg]
|
||||
Repack boot image components using files from the current directory
|
||||
to [outbootimg], or 'new-boot.img' if not specified.
|
||||
to [outbootimg], or 'new-boot.img' if not specified. Current directory
|
||||
should only contain required files for [outbootimg], or incorrect
|
||||
[outbootimg] may be produced.
|
||||
<origbootimg> is the original boot image used to unpack the components.
|
||||
By default, each component will be automatically compressed using its
|
||||
corresponding format detected in <origbootimg>. If a component file
|
||||
@@ -150,6 +152,8 @@ int main(int argc, char *argv[]) {
|
||||
unlink(EXTRA_FILE);
|
||||
unlink(RECV_DTBO_FILE);
|
||||
unlink(DTB_FILE);
|
||||
unlink(BOOTCONFIG_FILE);
|
||||
rm_rf(VND_RAMDISK_DIR);
|
||||
} else if (argc > 2 && action == "sha1") {
|
||||
uint8_t sha1[20];
|
||||
{
|
||||
|
@@ -230,7 +230,9 @@ kv_pairs load_partition_map() {
|
||||
}
|
||||
|
||||
bool check_two_stage() {
|
||||
if (access("/apex", F_OK) == 0)
|
||||
if (access("/first_stage_ramdisk", F_OK) == 0)
|
||||
return true;
|
||||
if (access("/second_stage_resources", F_OK) == 0)
|
||||
return true;
|
||||
if (access("/system/bin/init", F_OK) == 0)
|
||||
return true;
|
||||
|
@@ -90,15 +90,17 @@ int main(int argc, char *argv[]) {
|
||||
} else {
|
||||
// This will also mount /sys and /proc
|
||||
load_kernel_info(&config);
|
||||
bool recovery = access("/sbin/recovery", F_OK) == 0 ||
|
||||
access("/system/bin/recovery", F_OK) == 0;
|
||||
|
||||
if (config.skip_initramfs)
|
||||
if (config.force_normal_boot)
|
||||
init = new FirstStageInit(argv, &config);
|
||||
else if (!recovery && check_two_stage())
|
||||
init = new FirstStageInit(argv, &config);
|
||||
else if (config.skip_initramfs)
|
||||
init = new LegacySARInit(argv, &config);
|
||||
else if (config.force_normal_boot)
|
||||
init = new FirstStageInit(argv, &config);
|
||||
else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0)
|
||||
else if (recovery)
|
||||
init = new RecoveryInit(argv, &config);
|
||||
else if (check_two_stage())
|
||||
init = new FirstStageInit(argv, &config);
|
||||
else
|
||||
init = new RootFSInit(argv, &config);
|
||||
}
|
||||
|
@@ -200,8 +200,7 @@ mount_root:
|
||||
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
|
||||
mount_list.emplace_back("/dev");
|
||||
|
||||
// Use the apex folder to determine whether 2SI (Android 10+)
|
||||
bool is_two_stage = access("/apex", F_OK) == 0;
|
||||
bool is_two_stage = access("/system/bin/init", F_OK) == 0;
|
||||
LOGD("is_two_stage: [%d]\n", is_two_stage);
|
||||
|
||||
// For API 28 AVD, it uses legacy SAR setup that requires
|
||||
|
@@ -14,7 +14,6 @@ pub fn inject_magisk_rc(fd: RawFd, tmp_dir: &Utf8CStr) {
|
||||
file,
|
||||
r#"
|
||||
on post-fs-data
|
||||
start logd
|
||||
exec {0} 0 0 -- {1}/magisk --post-fs-data
|
||||
|
||||
on property:vold.decrypt=trigger_restart_framework
|
||||
|
@@ -189,6 +189,15 @@ printvar() {
|
||||
eval echo $1=\$$1
|
||||
}
|
||||
|
||||
run_action() {
|
||||
local MODID="$1"
|
||||
cd "/data/adb/modules/$MODID"
|
||||
sh ./action.sh
|
||||
local RES=$?
|
||||
cd /
|
||||
return $RES
|
||||
}
|
||||
|
||||
##########################
|
||||
# Non-root util_functions
|
||||
##########################
|
||||
|
@@ -206,7 +206,7 @@ fi
|
||||
|
||||
yes | "$sdk" --licenses > /dev/null
|
||||
curl -L $lsposed_url -o out/lsposed.zip
|
||||
"$sdk" --channel=3 tools platform-tools emulator
|
||||
"$sdk" --channel=3 platform-tools emulator
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
run_test $1 $2
|
||||
|
@@ -220,6 +220,13 @@ if [ -f kernel ]; then
|
||||
# After: [mov w2, #-32768]
|
||||
./magiskboot hexpatch kernel 821B8012 E2FF8F12 && PATCHEDKERNEL=true
|
||||
|
||||
# Disable Samsung PROCA
|
||||
# proca_config -> proca_magisk
|
||||
./magiskboot hexpatch kernel \
|
||||
70726F63615F636F6E66696700 \
|
||||
70726F63615F6D616769736B00 \
|
||||
&& PATCHEDKERNEL=true
|
||||
|
||||
# Force kernel to load rootfs for legacy SAR devices
|
||||
# skip_initramfs -> want_initramfs
|
||||
$LEGACYSAR && ./magiskboot hexpatch kernel \
|
||||
|
Reference in New Issue
Block a user