diff --git a/app/build.gradle b/app/build.gradle index 2bd136737..c335fa2a2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -74,7 +74,7 @@ dependencies { implementation "${bindingAdapter}:${vBAdapt}" implementation "${bindingAdapter}-recyclerview:${vBAdapt}" - def vMarkwon = '4.1.2' + def vMarkwon = '4.2.0' implementation "io.noties.markwon:core:${vMarkwon}" implementation "io.noties.markwon:html:${vMarkwon}" implementation "io.noties.markwon:image:${vMarkwon}" @@ -99,7 +99,7 @@ dependencies { implementation "com.squareup.okhttp3:okhttp:${vOkHttp}" implementation "com.squareup.okhttp3:logging-interceptor:${vOkHttp}" - def vMoshi = '1.9.1' + def vMoshi = '1.9.2' implementation "com.squareup.moshi:moshi:${vMoshi}" def vKotshi = '2.0.2' @@ -111,7 +111,7 @@ dependencies { replacedBy('com.github.topjohnwu:room-runtime') } } - def vRoom = '2.2.1' + def vRoom = '2.2.2' implementation "com.github.topjohnwu:room-runtime:${vRoom}" implementation "androidx.room:room-rxjava2:${vRoom}" kapt "androidx.room:room-compiler:${vRoom}" @@ -125,13 +125,12 @@ dependencies { implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03' implementation 'androidx.browser:browser:1.0.0' implementation 'androidx.preference:preference:1.1.0' - implementation 'androidx.recyclerview:recyclerview:1.1.0-rc01' - implementation 'androidx.fragment:fragment-ktx:1.2.0-rc02' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'androidx.fragment:fragment-ktx:1.2.0-rc03' implementation 'androidx.work:work-runtime:2.2.0' - implementation 'androidx.transition:transition:1.2.0' + implementation 'androidx.transition:transition:1.3.0-rc02' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.core:core-ktx:1.1.0' - implementation 'androidx.biometric:biometric:1.0.0' - implementation 'com.google.android.material:material:1.1.0-beta01' + implementation 'com.google.android.material:material:1.2.0-alpha01' implementation 'com.karumi:dexter:6.0.0' } diff --git a/app/src/main/java/com/topjohnwu/magisk/Config.kt b/app/src/main/java/com/topjohnwu/magisk/Config.kt index 2effcd5d7..07595d902 100644 --- a/app/src/main/java/com/topjohnwu/magisk/Config.kt +++ b/app/src/main/java/com/topjohnwu/magisk/Config.kt @@ -54,6 +54,7 @@ object Config : PreferenceModel, DBConfig { const val REDESIGN = "redesign" const val SAFETY = "safety_notice" const val THEME_ORDINAL = "theme_ordinal" + const val BOOT_ID = "boot_id" // system state const val MAGISKHIDE = "magiskhide" @@ -111,6 +112,8 @@ object Config : PreferenceModel, DBConfig { } else Value.DEFAULT_CHANNEL + var bootId by preference(Key.BOOT_ID, "") + var downloadPath by preference(Key.DOWNLOAD_PATH, Environment.DIRECTORY_DOWNLOADS) var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE) diff --git a/app/src/main/java/com/topjohnwu/magisk/Hacks.kt b/app/src/main/java/com/topjohnwu/magisk/Hacks.kt index 5437ec9d2..d3a683760 100644 --- a/app/src/main/java/com/topjohnwu/magisk/Hacks.kt +++ b/app/src/main/java/com/topjohnwu/magisk/Hacks.kt @@ -24,9 +24,6 @@ import com.topjohnwu.magisk.ui.flash.FlashActivity import com.topjohnwu.magisk.ui.surequest.SuRequestActivity import com.topjohnwu.magisk.utils.refreshLocale import com.topjohnwu.magisk.utils.updateConfig -import com.topjohnwu.magisk.utils.currentLocale -import com.topjohnwu.magisk.utils.defaultLocale -import java.util.* import com.topjohnwu.magisk.redesign.MainActivity as RedesignActivity fun AssetManager.addAssetPath(path: String) { diff --git a/app/src/main/java/com/topjohnwu/magisk/Info.kt b/app/src/main/java/com/topjohnwu/magisk/Info.kt index d1f7db086..0d1e3bb01 100644 --- a/app/src/main/java/com/topjohnwu/magisk/Info.kt +++ b/app/src/main/java/com/topjohnwu/magisk/Info.kt @@ -8,6 +8,8 @@ import com.topjohnwu.magisk.utils.CachedValue import com.topjohnwu.magisk.utils.KObservableField import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.ShellUtils +import java.io.FileInputStream +import java.io.IOException val isRunningAsStub get() = Info.stub != null @@ -36,6 +38,22 @@ object Info { } } + val isNewReboot by lazy { + try { + FileInputStream("/proc/sys/kernel/random/boot_id").bufferedReader().use { + val id = it.readLine() + if (id != Config.bootId) { + Config.bootId = id + true + } else { + false + } + } + } catch (e: IOException) { + false + } + } + private fun loadState() = runCatching { val str = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0] val code = ShellUtils.fastCmd("magisk -V").toInt() diff --git a/app/src/main/java/com/topjohnwu/magisk/data/database/PolicyDao.kt b/app/src/main/java/com/topjohnwu/magisk/data/database/PolicyDao.kt index ff73b6cb7..653b12e7a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/database/PolicyDao.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/database/PolicyDao.kt @@ -3,8 +3,8 @@ package com.topjohnwu.magisk.data.database import android.content.Context import android.content.pm.PackageManager import com.topjohnwu.magisk.Const -import com.topjohnwu.magisk.data.database.magiskdb.Delete import com.topjohnwu.magisk.data.database.magiskdb.BaseDao +import com.topjohnwu.magisk.data.database.magiskdb.Delete import com.topjohnwu.magisk.data.database.magiskdb.Replace import com.topjohnwu.magisk.data.database.magiskdb.Select import com.topjohnwu.magisk.extensions.now diff --git a/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt b/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt index c2b4a2701..fdc00d520 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt @@ -1,7 +1,7 @@ package com.topjohnwu.magisk.data.database -import com.topjohnwu.magisk.data.database.magiskdb.Delete import com.topjohnwu.magisk.data.database.magiskdb.BaseDao +import com.topjohnwu.magisk.data.database.magiskdb.Delete import com.topjohnwu.magisk.data.database.magiskdb.Replace import com.topjohnwu.magisk.data.database.magiskdb.Select diff --git a/app/src/main/java/com/topjohnwu/magisk/data/database/StringDao.kt b/app/src/main/java/com/topjohnwu/magisk/data/database/StringDao.kt index 92b8c458b..24eab0564 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/database/StringDao.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/database/StringDao.kt @@ -1,7 +1,7 @@ package com.topjohnwu.magisk.data.database -import com.topjohnwu.magisk.data.database.magiskdb.Delete import com.topjohnwu.magisk.data.database.magiskdb.BaseDao +import com.topjohnwu.magisk.data.database.magiskdb.Delete import com.topjohnwu.magisk.data.database.magiskdb.Replace import com.topjohnwu.magisk.data.database.magiskdb.Select diff --git a/app/src/main/java/com/topjohnwu/magisk/extensions/XAndroid.kt b/app/src/main/java/com/topjohnwu/magisk/extensions/XAndroid.kt index 2d9a9e87d..24da3e04b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/extensions/XAndroid.kt +++ b/app/src/main/java/com/topjohnwu/magisk/extensions/XAndroid.kt @@ -33,8 +33,8 @@ import com.topjohnwu.magisk.FileProvider import com.topjohnwu.magisk.utils.DynamicClassLoader import com.topjohnwu.magisk.utils.Utils import com.topjohnwu.magisk.utils.currentLocale -import com.topjohnwu.superuser.ShellUtils import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.ShellUtils import java.io.File import java.io.FileNotFoundException import java.text.SimpleDateFormat @@ -344,4 +344,4 @@ val isSAR val isAB get() = ShellUtils .fastCmd("grep_prop ro.build.ab_update") - .let { it.isNotEmpty() && it.toBoolean() } \ No newline at end of file + .let { it.isNotEmpty() && it.toBoolean() } diff --git a/app/src/main/java/com/topjohnwu/magisk/extensions/XJava.kt b/app/src/main/java/com/topjohnwu/magisk/extensions/XJava.kt index 67dbcc134..4a149528e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/extensions/XJava.kt +++ b/app/src/main/java/com/topjohnwu/magisk/extensions/XJava.kt @@ -1,7 +1,6 @@ package com.topjohnwu.magisk.extensions import android.os.Build -import androidx.core.net.toFile import timber.log.Timber import java.io.File import java.io.InputStream diff --git a/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt b/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt index 9e1a41b8e..bb46bddcd 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt @@ -3,7 +3,6 @@ package com.topjohnwu.magisk.model.download import android.app.Activity import android.app.Notification import android.content.Intent -import androidx.core.app.NotificationCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.topjohnwu.magisk.R diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/module/Module.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/module/Module.kt index 8017dea4d..1da190682 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/module/Module.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/module/Module.kt @@ -13,17 +13,21 @@ class Module(path: String) : BaseModule() { override var versionCode: Int = -1 override var description: String = "" - private val removeFile: SuFile = SuFile(path, "remove") - private val disableFile: SuFile = SuFile(path, "disable") - private val updateFile: SuFile = SuFile(path, "update") + private val removeFile = SuFile(path, "remove") + private val disableFile = SuFile(path, "disable") + private val updateFile = SuFile(path, "update") + private val ruleFile = SuFile(path, "sepolicy.rule") val updated: Boolean = updateFile.exists() var enable: Boolean = !disableFile.exists() set(enable) { + val dir = "$PERSIST/$id" field = if (enable) { + Shell.su("mkdir -p $dir", "cp -af $ruleFile $dir").submit() disableFile.delete() } else { + Shell.su("rm -rf $dir").submit() !disableFile.createNewFile() } } @@ -31,8 +35,10 @@ class Module(path: String) : BaseModule() { var remove: Boolean = removeFile.exists() set(remove) { field = if (remove) { + Shell.su("rm -rf $PERSIST/$id").submit() removeFile.createNewFile() } else { + Shell.su("cp -af $ruleFile $PERSIST/$id").submit() !removeFile.delete() } } @@ -54,6 +60,8 @@ class Module(path: String) : BaseModule() { companion object { + private const val PERSIST = "/sbin/.magisk/mirror/persist/magisk" + @WorkerThread fun loadModules(): List { val moduleList = mutableListOf() diff --git a/app/src/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.kt b/app/src/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.kt index e6de79548..19598e116 100644 --- a/app/src/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.kt +++ b/app/src/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.kt @@ -287,8 +287,10 @@ abstract class MagiskInstaller { protected fun flashBoot(): Boolean { if (!"direct_install $installDir $srcBoot".sh().isSuccess) return false - if (!Info.keepVerity) - "patch_dtbo_image".sh() + arrayOf( + "(KEEPVERITY=${Info.keepVerity} patch_dtb_partitions)", + "run_migrations" + ).sh() return true } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt index 8e7f2b0ba..ad942ae0a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt @@ -3,18 +3,16 @@ package com.topjohnwu.magisk.ui import android.app.Activity import android.content.Context import android.os.Bundle -import android.text.TextUtils -import androidx.appcompat.app.AlertDialog -import com.topjohnwu.magisk.* -import com.topjohnwu.magisk.model.navigation.Navigation import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.Config -import com.topjohnwu.magisk.intent +import com.topjohnwu.magisk.Info +import com.topjohnwu.magisk.model.navigation.Navigation import com.topjohnwu.magisk.utils.Utils import com.topjohnwu.magisk.view.Notifications import com.topjohnwu.magisk.view.Shortcuts import com.topjohnwu.magisk.wrap import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.ShellUtils open class SplashActivity : Activity() { @@ -41,6 +39,10 @@ open class SplashActivity : Activity() { } } + Info.keepVerity = ShellUtils.fastCmd("echo \$KEEPVERITY").toBoolean() + Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean() + Info.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean() + // Set default configs Config.initialize() @@ -53,9 +55,13 @@ open class SplashActivity : Activity() { // Setup shortcuts Shortcuts.setup(this) - Shell.su("mm_patch_dtbo").submit { - if (it.isSuccess) - Notifications.dtboPatched(this) + if (Info.isNewReboot) { + val shell = Shell.newInstance() + shell.newJob().add("mm_patch_dtb").submit { + if (it.isSuccess) + Notifications.dtboPatched(this) + shell.close() + } } DONE = true diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt b/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt index c7c01a1d1..92d5a2729 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt @@ -2,12 +2,10 @@ package com.topjohnwu.magisk.utils import android.content.Context import com.topjohnwu.magisk.Const -import com.topjohnwu.magisk.Info import com.topjohnwu.magisk.R import com.topjohnwu.magisk.extensions.rawResource import com.topjohnwu.magisk.wrap import com.topjohnwu.superuser.Shell -import com.topjohnwu.superuser.ShellUtils import com.topjohnwu.superuser.io.SuFile class RootInit : Shell.Initializer() { @@ -17,9 +15,6 @@ class RootInit : Shell.Initializer() { } fun init(context: Context, shell: Shell): Boolean { - // Invalidate env state if shell is recreated - Info.envRef.invalidate() - val job = shell.newJob() if (shell.isRoot) { job.add(context.rawResource(R.raw.util_functions)) @@ -29,15 +24,12 @@ class RootInit : Shell.Initializer() { job.add(context.rawResource(R.raw.nonroot_utils)) } - job.add("mount_partitions", - "get_flags", - "run_migrations", - "export BOOTMODE=true") - .exec() - - Info.keepVerity = ShellUtils.fastCmd("echo \$KEEPVERITY").toBoolean() - Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean() - Info.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean() + job.add( + "mount_partitions", + "get_flags", + "run_migrations", + "export BOOTMODE=true" + ).exec() return true } diff --git a/app/src/main/res/font/exo_bold_italic.ttf b/app/src/main/res/font/exo_bold_italic.ttf index 74c02b21e..9f446bd11 100755 Binary files a/app/src/main/res/font/exo_bold_italic.ttf and b/app/src/main/res/font/exo_bold_italic.ttf differ diff --git a/app/src/main/res/layout/fragment_modules.xml b/app/src/main/res/layout/fragment_modules.xml index 6c6b8f6da..7439ca496 100644 --- a/app/src/main/res/layout/fragment_modules.xml +++ b/app/src/main/res/layout/fragment_modules.xml @@ -59,10 +59,12 @@ android:layout_gravity="bottom|center_horizontal" android:layout_margin="@dimen/fab_padding" android:onClick="@{() -> viewModel.fabPressed()}" + android:focusable="true" + android:clickable="true" app:fabSize="normal" app:layout_behavior="com.google.android.material.floatingactionbutton.FloatingActionButton$Behavior" app:srcCompat="@drawable/ic_add" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_console.xml b/app/src/main/res/layout/item_console.xml index b0c4d4fb7..8fa6c0b93 100644 --- a/app/src/main/res/layout/item_console.xml +++ b/app/src/main/res/layout/item_console.xml @@ -16,6 +16,7 @@ - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_repo.xml b/app/src/main/res/layout/item_repo.xml index 6e876e5ea..efada5183 100644 --- a/app/src/main/res/layout/item_repo.xml +++ b/app/src/main/res/layout/item_repo.xml @@ -105,6 +105,8 @@