Separate core components
This commit is contained in:
parent
ba1a2fbce4
commit
707d7b3342
10
app/proguard-rules.pro
vendored
10
app/proguard-rules.pro
vendored
@ -17,9 +17,9 @@
|
|||||||
#}
|
#}
|
||||||
|
|
||||||
# Snet
|
# Snet
|
||||||
-keepclassmembers class com.topjohnwu.magisk.utils.SafetyNetHelper { *; }
|
-keepclassmembers class com.topjohnwu.magisk.core.utils.SafetyNetHelper { *; }
|
||||||
-keep,allowobfuscation interface com.topjohnwu.magisk.utils.SafetyNetHelper$Callback
|
-keep,allowobfuscation interface com.topjohnwu.magisk.core.utils.SafetyNetHelper$Callback
|
||||||
-keepclassmembers class * implements com.topjohnwu.magisk.utils.SafetyNetHelper$Callback {
|
-keepclassmembers class * implements com.topjohnwu.magisk.core.utils.SafetyNetHelper$Callback {
|
||||||
void onResponse(int);
|
void onResponse(int);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,13 +29,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
# DelegateWorker
|
# DelegateWorker
|
||||||
-keep,allowobfuscation class * extends com.topjohnwu.magisk.base.DelegateWorker
|
-keep,allowobfuscation class * extends com.topjohnwu.magisk.core.base.BaseWorkerWrapper
|
||||||
|
|
||||||
# BootSigner
|
# BootSigner
|
||||||
-keep class a.a { *; }
|
-keep class a.a { *; }
|
||||||
|
|
||||||
# Workaround R8 bug
|
# Workaround R8 bug
|
||||||
-keep,allowobfuscation class com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
-keep,allowobfuscation class com.topjohnwu.magisk.core.GeneralReceiver
|
||||||
-keepclassmembers class a.e { *; }
|
-keepclassmembers class a.e { *; }
|
||||||
|
|
||||||
# Strip logging
|
# Strip logging
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package a;
|
package a;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.PatchAPK;
|
import com.topjohnwu.magisk.core.utils.PatchAPK;
|
||||||
import com.topjohnwu.signing.BootSigner;
|
import com.topjohnwu.signing.BootSigner;
|
||||||
|
|
||||||
public class a {
|
public class a {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package a;
|
package a;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.ui.SplashActivity;
|
import com.topjohnwu.magisk.core.SplashActivity;
|
||||||
|
|
||||||
public class c extends SplashActivity {
|
public class c extends SplashActivity {
|
||||||
/* stub */
|
/* stub */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package a;
|
package a;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.App;
|
import com.topjohnwu.magisk.core.App;
|
||||||
|
|
||||||
public class e extends App {
|
public class e extends App {
|
||||||
public e() {
|
public e() {
|
||||||
|
@ -5,7 +5,7 @@ import android.content.Context;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.work.WorkerParameters;
|
import androidx.work.WorkerParameters;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.model.update.UpdateCheckService;
|
import com.topjohnwu.magisk.core.UpdateCheckService;
|
||||||
|
|
||||||
public class g extends w<UpdateCheckService> {
|
public class g extends w<UpdateCheckService> {
|
||||||
/* Stub */
|
/* Stub */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package a;
|
package a;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.model.receiver.GeneralReceiver;
|
import com.topjohnwu.magisk.core.GeneralReceiver;
|
||||||
|
|
||||||
public class h extends GeneralReceiver {
|
public class h extends GeneralReceiver {
|
||||||
/* stub */
|
/* stub */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package a;
|
package a;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService;
|
import com.topjohnwu.magisk.core.download.DownloadService;
|
||||||
|
|
||||||
public class j extends DownloadService {
|
public class j extends DownloadService {
|
||||||
/* stub */
|
/* stub */
|
||||||
|
@ -6,11 +6,11 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.work.Worker;
|
import androidx.work.Worker;
|
||||||
import androidx.work.WorkerParameters;
|
import androidx.work.WorkerParameters;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.base.DelegateWorker;
|
import com.topjohnwu.magisk.core.base.BaseWorkerWrapper;
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
|
||||||
public abstract class w<T extends DelegateWorker> extends Worker {
|
public abstract class w<T extends BaseWorkerWrapper> extends Worker {
|
||||||
|
|
||||||
/* Wrapper class to workaround Proguard -keep class * extends Worker */
|
/* Wrapper class to workaround Proguard -keep class * extends Worker */
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -9,6 +9,12 @@ import androidx.room.Room
|
|||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.impl.WorkDatabase
|
import androidx.work.impl.WorkDatabase
|
||||||
import androidx.work.impl.WorkDatabase_Impl
|
import androidx.work.impl.WorkDatabase_Impl
|
||||||
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.DynAPK
|
||||||
|
import com.topjohnwu.magisk.FileProvider
|
||||||
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||||
|
import com.topjohnwu.magisk.core.utils.RootInit
|
||||||
|
import com.topjohnwu.magisk.core.utils.updateConfig
|
||||||
import com.topjohnwu.magisk.data.database.RepoDatabase
|
import com.topjohnwu.magisk.data.database.RepoDatabase
|
||||||
import com.topjohnwu.magisk.data.database.RepoDatabase_Impl
|
import com.topjohnwu.magisk.data.database.RepoDatabase_Impl
|
||||||
import com.topjohnwu.magisk.data.database.SuLogDatabase
|
import com.topjohnwu.magisk.data.database.SuLogDatabase
|
||||||
@ -17,9 +23,6 @@ import com.topjohnwu.magisk.di.ActivityTracker
|
|||||||
import com.topjohnwu.magisk.di.koinModules
|
import com.topjohnwu.magisk.di.koinModules
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.unwrap
|
import com.topjohnwu.magisk.extensions.unwrap
|
||||||
import com.topjohnwu.magisk.utils.RootInit
|
|
||||||
import com.topjohnwu.magisk.utils.SuHandler
|
|
||||||
import com.topjohnwu.magisk.utils.updateConfig
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
import org.koin.core.context.startKoin
|
import org.koin.core.context.startKoin
|
||||||
@ -37,7 +40,7 @@ open class App() : Application() {
|
|||||||
Shell.Config.verboseLogging(BuildConfig.DEBUG)
|
Shell.Config.verboseLogging(BuildConfig.DEBUG)
|
||||||
Shell.Config.addInitializers(RootInit::class.java)
|
Shell.Config.addInitializers(RootInit::class.java)
|
||||||
Shell.Config.setTimeout(2)
|
Shell.Config.setTimeout(2)
|
||||||
FileProvider.callHandler = SuHandler
|
FileProvider.callHandler = SuCallbackHandler
|
||||||
Room.setFactory {
|
Room.setFactory {
|
||||||
when (it) {
|
when (it) {
|
||||||
WorkDatabase::class.java -> WorkDatabase_Impl()
|
WorkDatabase::class.java -> WorkDatabase_Impl()
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
@ -6,16 +6,17 @@ import android.os.Environment
|
|||||||
import android.util.Xml
|
import android.util.Xml
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import com.topjohnwu.magisk.data.database.SettingsDao
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
import com.topjohnwu.magisk.data.database.StringDao
|
import com.topjohnwu.magisk.core.magiskdb.SettingsDao
|
||||||
|
import com.topjohnwu.magisk.core.magiskdb.StringDao
|
||||||
import com.topjohnwu.magisk.data.repository.DBConfig
|
import com.topjohnwu.magisk.data.repository.DBConfig
|
||||||
import com.topjohnwu.magisk.di.Protected
|
import com.topjohnwu.magisk.di.Protected
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.inject
|
import com.topjohnwu.magisk.extensions.inject
|
||||||
import com.topjohnwu.magisk.model.preference.PreferenceModel
|
import com.topjohnwu.magisk.model.preference.PreferenceModel
|
||||||
import com.topjohnwu.magisk.ui.theme.Theme
|
import com.topjohnwu.magisk.ui.theme.Theme
|
||||||
import com.topjohnwu.magisk.utils.BiometricHelper
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
import com.topjohnwu.superuser.io.SuFileInputStream
|
import com.topjohnwu.superuser.io.SuFileInputStream
|
||||||
@ -115,12 +116,24 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
var bootId by preference(Key.BOOT_ID, "")
|
var bootId by preference(Key.BOOT_ID, "")
|
||||||
|
|
||||||
var downloadPath by preference(Key.DOWNLOAD_PATH, Environment.DIRECTORY_DOWNLOADS)
|
var downloadPath by preference(Key.DOWNLOAD_PATH, Environment.DIRECTORY_DOWNLOADS)
|
||||||
var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE)
|
var repoOrder by preference(
|
||||||
|
Key.REPO_ORDER,
|
||||||
|
Value.ORDER_DATE
|
||||||
|
)
|
||||||
|
|
||||||
var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10)
|
var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10)
|
||||||
var suAutoReponse by preferenceStrInt(Key.SU_AUTO_RESPONSE, Value.SU_PROMPT)
|
var suAutoReponse by preferenceStrInt(
|
||||||
var suNotification by preferenceStrInt(Key.SU_NOTIFICATION, Value.NOTIFICATION_TOAST)
|
Key.SU_AUTO_RESPONSE,
|
||||||
var updateChannel by preferenceStrInt(Key.UPDATE_CHANNEL, defaultChannel)
|
Value.SU_PROMPT
|
||||||
|
)
|
||||||
|
var suNotification by preferenceStrInt(
|
||||||
|
Key.SU_NOTIFICATION,
|
||||||
|
Value.NOTIFICATION_TOAST
|
||||||
|
)
|
||||||
|
var updateChannel by preferenceStrInt(
|
||||||
|
Key.UPDATE_CHANNEL,
|
||||||
|
defaultChannel
|
||||||
|
)
|
||||||
|
|
||||||
var safetyNotice by preference(Key.SAFETY, true)
|
var safetyNotice by preference(Key.SAFETY, true)
|
||||||
var darkThemeExtended by preference(
|
var darkThemeExtended by preference(
|
||||||
@ -139,9 +152,18 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
||||||
var locale by preference(Key.LOCALE, "")
|
var locale by preference(Key.LOCALE, "")
|
||||||
|
|
||||||
var rootMode by dbSettings(Key.ROOT_ACCESS, Value.ROOT_ACCESS_APPS_AND_ADB)
|
var rootMode by dbSettings(
|
||||||
var suMntNamespaceMode by dbSettings(Key.SU_MNT_NS, Value.NAMESPACE_MODE_REQUESTER)
|
Key.ROOT_ACCESS,
|
||||||
var suMultiuserMode by dbSettings(Key.SU_MULTIUSER_MODE, Value.MULTIUSER_MODE_OWNER_ONLY)
|
Value.ROOT_ACCESS_APPS_AND_ADB
|
||||||
|
)
|
||||||
|
var suMntNamespaceMode by dbSettings(
|
||||||
|
Key.SU_MNT_NS,
|
||||||
|
Value.NAMESPACE_MODE_REQUESTER
|
||||||
|
)
|
||||||
|
var suMultiuserMode by dbSettings(
|
||||||
|
Key.SU_MULTIUSER_MODE,
|
||||||
|
Value.MULTIUSER_MODE_OWNER_ONLY
|
||||||
|
)
|
||||||
var suBiometric by dbSettings(Key.SU_BIOMETRIC, false)
|
var suBiometric by dbSettings(Key.SU_BIOMETRIC, false)
|
||||||
var suManager by dbStrings(Key.SU_MANAGER, "", true)
|
var suManager by dbStrings(Key.SU_MANAGER, "", true)
|
||||||
var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true)
|
var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true)
|
||||||
@ -177,7 +199,9 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parsePrefs(editor: SharedPreferences.Editor) = editor.apply {
|
private fun parsePrefs(editor: SharedPreferences.Editor) = editor.apply {
|
||||||
val config = SuFile.open("/data/adb", Const.MANAGER_CONFIGS)
|
val config = SuFile.open("/data/adb",
|
||||||
|
Const.MANAGER_CONFIGS
|
||||||
|
)
|
||||||
if (config.exists()) runCatching {
|
if (config.exists()) runCatching {
|
||||||
val input = SuFileInputStream(config)
|
val input = SuFileInputStream(config)
|
||||||
val parser = Xml.newPullParser()
|
val parser = Xml.newPullParser()
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.os.Process
|
import android.os.Process
|
||||||
import java.io.File
|
import java.io.File
|
@ -1,19 +1,16 @@
|
|||||||
package com.topjohnwu.magisk.model.receiver
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.core.base.BaseReceiver
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.magiskdb.PolicyDao
|
||||||
import com.topjohnwu.magisk.base.BaseReceiver
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||||
import com.topjohnwu.magisk.data.database.PolicyDao
|
|
||||||
import com.topjohnwu.magisk.extensions.reboot
|
import com.topjohnwu.magisk.extensions.reboot
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService
|
import com.topjohnwu.magisk.core.model.ManagerJson
|
||||||
import com.topjohnwu.magisk.model.entity.ManagerJson
|
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.utils.SuHandler
|
import com.topjohnwu.magisk.core.view.Shortcuts
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import org.koin.core.inject
|
import org.koin.core.inject
|
||||||
|
|
||||||
@ -30,7 +27,11 @@ open class GeneralReceiver : BaseReceiver() {
|
|||||||
|
|
||||||
when (intent.action ?: return) {
|
when (intent.action ?: return) {
|
||||||
Intent.ACTION_REBOOT -> {
|
Intent.ACTION_REBOOT -> {
|
||||||
SuHandler(context, intent.getStringExtra("action"), intent.extras)
|
SuCallbackHandler(
|
||||||
|
context,
|
||||||
|
intent.getStringExtra("action"),
|
||||||
|
intent.extras
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Intent.ACTION_PACKAGE_REPLACED -> {
|
Intent.ACTION_PACKAGE_REPLACED -> {
|
||||||
// This will only work pre-O
|
// This will only work pre-O
|
@ -1,6 +1,6 @@
|
|||||||
@file:Suppress("DEPRECATION")
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package com.topjohnwu.magisk
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.job.JobInfo
|
import android.app.job.JobInfo
|
||||||
@ -14,16 +14,15 @@ import android.content.res.AssetManager
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import com.topjohnwu.magisk.DynAPK
|
||||||
|
import com.topjohnwu.magisk.ProcessPhoenix
|
||||||
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
|
import com.topjohnwu.magisk.core.utils.refreshLocale
|
||||||
|
import com.topjohnwu.magisk.core.utils.updateConfig
|
||||||
import com.topjohnwu.magisk.extensions.forceGetDeclaredField
|
import com.topjohnwu.magisk.extensions.forceGetDeclaredField
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService
|
|
||||||
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
|
||||||
import com.topjohnwu.magisk.model.update.UpdateCheckService
|
|
||||||
import com.topjohnwu.magisk.ui.MainActivity
|
|
||||||
import com.topjohnwu.magisk.ui.SplashActivity
|
|
||||||
import com.topjohnwu.magisk.legacy.flash.FlashActivity
|
import com.topjohnwu.magisk.legacy.flash.FlashActivity
|
||||||
import com.topjohnwu.magisk.legacy.surequest.SuRequestActivity
|
import com.topjohnwu.magisk.legacy.surequest.SuRequestActivity
|
||||||
import com.topjohnwu.magisk.utils.refreshLocale
|
import com.topjohnwu.magisk.ui.MainActivity
|
||||||
import com.topjohnwu.magisk.utils.updateConfig
|
|
||||||
|
|
||||||
fun AssetManager.addAssetPath(path: String) {
|
fun AssetManager.addAssetPath(path: String) {
|
||||||
DynAPK.addAssetPath(this, path)
|
DynAPK.addAssetPath(this, path)
|
@ -1,9 +1,10 @@
|
|||||||
package com.topjohnwu.magisk
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.topjohnwu.magisk.DynAPK
|
||||||
|
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.subscribeK
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.model.entity.UpdateInfo
|
|
||||||
import com.topjohnwu.magisk.utils.CachedValue
|
import com.topjohnwu.magisk.utils.CachedValue
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
@ -1,16 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.ui
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.Info
|
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
import com.topjohnwu.magisk.model.navigation.Navigation
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.core.view.Notifications
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
import com.topjohnwu.magisk.core.view.Shortcuts
|
||||||
import com.topjohnwu.magisk.wrap
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
|
|
@ -1,15 +1,14 @@
|
|||||||
package com.topjohnwu.magisk.model.update
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import androidx.work.ListenableWorker
|
import androidx.work.ListenableWorker
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.base.BaseWorkerWrapper
|
||||||
import com.topjohnwu.magisk.base.DelegateWorker
|
import com.topjohnwu.magisk.core.view.Notifications
|
||||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||||
import com.topjohnwu.magisk.extensions.inject
|
import com.topjohnwu.magisk.extensions.inject
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
|
|
||||||
class UpdateCheckService : DelegateWorker() {
|
class UpdateCheckService : BaseWorkerWrapper() {
|
||||||
|
|
||||||
private val magiskRepo: MagiskRepository by inject()
|
private val magiskRepo: MagiskRepository by inject()
|
||||||
|
|
@ -1,47 +1,26 @@
|
|||||||
package com.topjohnwu.magisk.base
|
package com.topjohnwu.magisk.core.base
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.collection.SparseArrayCompat
|
import androidx.collection.SparseArrayCompat
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.databinding.DataBindingUtil
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
import androidx.databinding.ViewDataBinding
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import com.topjohnwu.magisk.BR
|
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.extensions.set
|
import com.topjohnwu.magisk.extensions.set
|
||||||
import com.topjohnwu.magisk.model.events.EventHandler
|
|
||||||
import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
|
import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
|
||||||
import com.topjohnwu.magisk.utils.currentLocale
|
|
||||||
import com.topjohnwu.magisk.wrap
|
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
typealias RequestCallback = BaseActivity<*, *>.(Int, Intent?) -> Unit
|
typealias RequestCallback = BaseActivity.(Int, Intent?) -> Unit
|
||||||
|
|
||||||
abstract class BaseActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
abstract class BaseActivity : AppCompatActivity() {
|
||||||
AppCompatActivity(), EventHandler {
|
|
||||||
|
|
||||||
protected lateinit var binding: Binding
|
|
||||||
protected abstract val layoutRes: Int
|
|
||||||
protected abstract val viewModel: ViewModel
|
|
||||||
protected open val themeRes: Int = R.style.MagiskTheme
|
|
||||||
|
|
||||||
open val snackbarView get() = binding.root
|
|
||||||
|
|
||||||
private val resultCallbacks by lazy { SparseArrayCompat<RequestCallback>() }
|
private val resultCallbacks by lazy { SparseArrayCompat<RequestCallback>() }
|
||||||
|
|
||||||
init {
|
|
||||||
val theme = Config.darkThemeExtended
|
|
||||||
AppCompatDelegate.setDefaultNightMode(theme)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun applyOverrideConfiguration(config: Configuration?) {
|
override fun applyOverrideConfiguration(config: Configuration?) {
|
||||||
// Force applying our preferred local
|
// Force applying our preferred local
|
||||||
config?.setLocale(currentLocale)
|
config?.setLocale(currentLocale)
|
||||||
@ -52,18 +31,6 @@ abstract class BaseActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding
|
|||||||
super.attachBaseContext(base.wrap(false))
|
super.attachBaseContext(base.wrap(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
setTheme(themeRes)
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
viewModel.viewEvents.observe(this, viewEventObserver)
|
|
||||||
|
|
||||||
binding = DataBindingUtil.setContentView<Binding>(this, layoutRes).apply {
|
|
||||||
setVariable(BR.viewModel, viewModel)
|
|
||||||
lifecycleOwner = this@BaseActivity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun withPermissions(vararg permissions: String, builder: PermissionRequestBuilder.() -> Unit) {
|
fun withPermissions(vararg permissions: String, builder: PermissionRequestBuilder.() -> Unit) {
|
||||||
val request = PermissionRequestBuilder().apply(builder).build()
|
val request = PermissionRequestBuilder().apply(builder).build()
|
||||||
val ungranted = permissions.filter {
|
val ungranted = permissions.filter {
|
||||||
@ -89,7 +56,7 @@ abstract class BaseActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(
|
override fun onRequestPermissionsResult(
|
||||||
requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
var success = true
|
var success = true
|
||||||
for (res in grantResults) {
|
for (res in grantResults) {
|
||||||
if (res != PackageManager.PERMISSION_GRANTED) {
|
if (res != PackageManager.PERMISSION_GRANTED) {
|
||||||
@ -97,18 +64,18 @@ abstract class BaseActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resultCallbacks[requestCode]?.apply {
|
resultCallbacks[requestCode]?.also {
|
||||||
resultCallbacks.remove(requestCode)
|
resultCallbacks.remove(requestCode)
|
||||||
invoke(this@BaseActivity, if (success) 1 else -1, null)
|
it(this@BaseActivity, if (success) 1 else -1, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
resultCallbacks[requestCode]?.apply {
|
resultCallbacks[requestCode]?.also {
|
||||||
resultCallbacks.remove(requestCode)
|
resultCallbacks.remove(requestCode)
|
||||||
invoke(this@BaseActivity, resultCode, data)
|
it(this@BaseActivity, resultCode, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.base
|
package com.topjohnwu.magisk.core.base
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.topjohnwu.magisk.wrap
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
|
|
||||||
abstract class BaseReceiver : BroadcastReceiver(), KoinComponent {
|
abstract class BaseReceiver : BroadcastReceiver(), KoinComponent {
|
@ -1,8 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.base
|
package com.topjohnwu.magisk.core.base
|
||||||
|
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.topjohnwu.magisk.wrap
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
|
|
||||||
abstract class BaseService : Service(), KoinComponent {
|
abstract class BaseService : Service(), KoinComponent {
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.base
|
package com.topjohnwu.magisk.core.base
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Network
|
import android.net.Network
|
||||||
@ -10,7 +10,7 @@ import androidx.work.ListenableWorker
|
|||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
abstract class DelegateWorker {
|
abstract class BaseWorkerWrapper {
|
||||||
|
|
||||||
private lateinit var worker: ListenableWorker
|
private lateinit var worker: ListenableWorker
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.model.download
|
package com.topjohnwu.magisk.core.download
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
@ -8,15 +8,15 @@ import android.content.Intent
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.intent
|
||||||
import com.topjohnwu.magisk.extensions.chooser
|
import com.topjohnwu.magisk.extensions.chooser
|
||||||
import com.topjohnwu.magisk.extensions.exists
|
import com.topjohnwu.magisk.extensions.exists
|
||||||
import com.topjohnwu.magisk.extensions.provide
|
import com.topjohnwu.magisk.extensions.provide
|
||||||
import com.topjohnwu.magisk.intent
|
import com.topjohnwu.magisk.legacy.flash.FlashActivity
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.*
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.*
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
||||||
import com.topjohnwu.magisk.legacy.flash.FlashActivity
|
|
||||||
import com.topjohnwu.magisk.utils.APKInstall
|
import com.topjohnwu.magisk.utils.APKInstall
|
||||||
import org.koin.core.get
|
import org.koin.core.get
|
||||||
import java.io.File
|
import java.io.File
|
@ -1,11 +1,18 @@
|
|||||||
package com.topjohnwu.magisk.model.download
|
package com.topjohnwu.magisk.core.download
|
||||||
|
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.DynAPK
|
||||||
|
import com.topjohnwu.magisk.ProcessPhoenix
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.intent
|
||||||
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
|
import com.topjohnwu.magisk.core.utils.PatchAPK
|
||||||
import com.topjohnwu.magisk.extensions.writeTo
|
import com.topjohnwu.magisk.extensions.writeTo
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.utils.PatchAPK
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.model.download
|
package com.topjohnwu.magisk.core.download
|
||||||
|
|
||||||
import com.topjohnwu.magisk.extensions.withStreams
|
import com.topjohnwu.magisk.extensions.withStreams
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -41,4 +41,4 @@ fun InputStream.toModule(file: File, installer: InputStream) {
|
|||||||
entry = zin.nextEntry
|
entry = zin.nextEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.model.download
|
package com.topjohnwu.magisk.core.download
|
||||||
|
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import com.topjohnwu.magisk.base.BaseService
|
import com.topjohnwu.magisk.core.base.BaseService
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.core.view.Notifications
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.random.Random.Default.nextInt
|
import kotlin.random.Random.Default.nextInt
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.model.download
|
package com.topjohnwu.magisk.core.download
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
@ -13,8 +13,8 @@ import com.topjohnwu.magisk.extensions.subscribeK
|
|||||||
import com.topjohnwu.magisk.extensions.writeTo
|
import com.topjohnwu.magisk.extensions.writeTo
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
||||||
import com.topjohnwu.magisk.utils.ProgressInputStream
|
import com.topjohnwu.magisk.core.utils.ProgressInputStream
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.core.view.Notifications
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.data.database.magiskdb
|
package com.topjohnwu.magisk.core.magiskdb
|
||||||
|
|
||||||
import androidx.annotation.StringDef
|
import androidx.annotation.StringDef
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
@ -1,16 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.data.database
|
package com.topjohnwu.magisk.core.magiskdb
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.data.database.magiskdb.BaseDao
|
import com.topjohnwu.magisk.core.model.MagiskPolicy
|
||||||
import com.topjohnwu.magisk.data.database.magiskdb.Delete
|
import com.topjohnwu.magisk.core.model.toMap
|
||||||
import com.topjohnwu.magisk.data.database.magiskdb.Replace
|
import com.topjohnwu.magisk.core.model.toPolicy
|
||||||
import com.topjohnwu.magisk.data.database.magiskdb.Select
|
|
||||||
import com.topjohnwu.magisk.extensions.now
|
import com.topjohnwu.magisk.extensions.now
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
|
||||||
import com.topjohnwu.magisk.model.entity.toMap
|
|
||||||
import com.topjohnwu.magisk.model.entity.toPolicy
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.data.database.magiskdb
|
package com.topjohnwu.magisk.core.magiskdb
|
||||||
|
|
||||||
import androidx.annotation.StringDef
|
import androidx.annotation.StringDef
|
||||||
|
|
@ -1,9 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.data.database
|
package com.topjohnwu.magisk.core.magiskdb
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
class SettingsDao : BaseDao() {
|
class SettingsDao : BaseDao() {
|
||||||
|
|
@ -1,9 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.data.database
|
package com.topjohnwu.magisk.core.magiskdb
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
class StringDao : BaseDao() {
|
class StringDao : BaseDao() {
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.model.entity
|
package com.topjohnwu.magisk.core.model
|
||||||
|
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.INTERACTIVE
|
||||||
import com.topjohnwu.magisk.extensions.getLabel
|
import com.topjohnwu.magisk.extensions.getLabel
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy.Companion.INTERACTIVE
|
|
||||||
|
|
||||||
|
|
||||||
data class MagiskPolicy(
|
data class MagiskPolicy(
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.model.entity
|
package com.topjohnwu.magisk.core.model
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.module
|
package com.topjohnwu.magisk.core.model.module
|
||||||
|
|
||||||
abstract class BaseModule : Comparable<BaseModule> {
|
abstract class BaseModule : Comparable<BaseModule> {
|
||||||
abstract var id: String
|
abstract var id: String
|
@ -1,7 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.module
|
package com.topjohnwu.magisk.core.model.module
|
||||||
|
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.module
|
package com.topjohnwu.magisk.core.model.module
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.data.repository.StringRepository
|
import com.topjohnwu.magisk.data.repository.StringRepository
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.legalFilename
|
import com.topjohnwu.magisk.extensions.legalFilename
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.su
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -6,20 +6,26 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Process
|
import android.os.Process
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.ProviderCallHandler
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.intent
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy
|
||||||
|
import com.topjohnwu.magisk.core.model.toPolicy
|
||||||
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import com.topjohnwu.magisk.data.repository.LogRepository
|
import com.topjohnwu.magisk.data.repository.LogRepository
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.startActivity
|
import com.topjohnwu.magisk.extensions.startActivity
|
||||||
import com.topjohnwu.magisk.extensions.startActivityWithRoot
|
import com.topjohnwu.magisk.extensions.startActivityWithRoot
|
||||||
import com.topjohnwu.magisk.extensions.subscribeK
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
|
||||||
import com.topjohnwu.magisk.model.entity.toLog
|
|
||||||
import com.topjohnwu.magisk.model.entity.toPolicy
|
|
||||||
import com.topjohnwu.magisk.legacy.surequest.SuRequestActivity
|
import com.topjohnwu.magisk.legacy.surequest.SuRequestActivity
|
||||||
|
import com.topjohnwu.magisk.model.entity.toLog
|
||||||
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
object SuHandler : ProviderCallHandler {
|
object SuCallbackHandler : ProviderCallHandler {
|
||||||
|
|
||||||
const val REQUEST = "request"
|
const val REQUEST = "request"
|
||||||
const val LOG = "log"
|
const val LOG = "log"
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.su
|
||||||
|
|
||||||
import android.net.LocalSocket
|
import android.net.LocalSocket
|
||||||
import android.net.LocalSocketAddress
|
import android.net.LocalSocketAddress
|
@ -0,0 +1,103 @@
|
|||||||
|
package com.topjohnwu.magisk.core.su
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.magiskdb.PolicyDao
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy
|
||||||
|
import com.topjohnwu.magisk.core.model.toPolicy
|
||||||
|
import com.topjohnwu.magisk.extensions.now
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
abstract class SuRequestHandler(
|
||||||
|
private val packageManager: PackageManager,
|
||||||
|
private val policyDB: PolicyDao
|
||||||
|
) {
|
||||||
|
protected var timer: CountDownTimer = object : CountDownTimer(
|
||||||
|
TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1)) {
|
||||||
|
override fun onFinish() {
|
||||||
|
respond(MagiskPolicy.DENY, 0)
|
||||||
|
}
|
||||||
|
override fun onTick(remains: Long) {}
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
field.cancel()
|
||||||
|
field = value
|
||||||
|
field.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected lateinit var policy: MagiskPolicy
|
||||||
|
|
||||||
|
private val cleanupTasks = mutableListOf<() -> Unit>()
|
||||||
|
private lateinit var connector: SuConnector
|
||||||
|
|
||||||
|
abstract fun onStart()
|
||||||
|
abstract fun onRespond()
|
||||||
|
|
||||||
|
fun start(intent: Intent): Boolean {
|
||||||
|
val socketName = intent.getStringExtra("socket") ?: return false
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector = object : SuConnector(socketName) {
|
||||||
|
override fun onResponse() {
|
||||||
|
out.writeInt(policy.policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val map = connector.readRequest()
|
||||||
|
val uid = map["uid"]?.toIntOrNull() ?: return false
|
||||||
|
policy = uid.toPolicy(packageManager)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never allow com.topjohnwu.magisk (could be malware)
|
||||||
|
if (policy.packageName == BuildConfig.APPLICATION_ID)
|
||||||
|
return false
|
||||||
|
|
||||||
|
when (Config.suAutoReponse) {
|
||||||
|
Config.Value.SU_AUTO_DENY -> {
|
||||||
|
respond(MagiskPolicy.DENY, 0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
Config.Value.SU_AUTO_ALLOW -> {
|
||||||
|
respond(MagiskPolicy.ALLOW, 0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.start()
|
||||||
|
cleanupTasks.add {
|
||||||
|
timer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
onStart()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun respond() {
|
||||||
|
connector.response()
|
||||||
|
cleanupTasks.forEach { it() }
|
||||||
|
onRespond()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun respond(action: Int, time: Int) {
|
||||||
|
val until = if (time > 0)
|
||||||
|
TimeUnit.MILLISECONDS.toSeconds(now) + TimeUnit.MINUTES.toSeconds(time.toLong())
|
||||||
|
else
|
||||||
|
time.toLong()
|
||||||
|
|
||||||
|
policy.policy = action
|
||||||
|
policy.until = until
|
||||||
|
policy.uid = policy.uid % 100000 + Const.USER_ID * 100000
|
||||||
|
|
||||||
|
if (until >= 0)
|
||||||
|
policyDB.update(policy).blockingAwait()
|
||||||
|
|
||||||
|
respond()
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.tasks
|
package com.topjohnwu.magisk.core.tasks
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.extensions.fileName
|
import com.topjohnwu.magisk.extensions.fileName
|
||||||
import com.topjohnwu.magisk.extensions.inject
|
import com.topjohnwu.magisk.extensions.inject
|
||||||
import com.topjohnwu.magisk.extensions.readUri
|
import com.topjohnwu.magisk.extensions.readUri
|
||||||
import com.topjohnwu.magisk.extensions.subscribeK
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.utils.unzip
|
import com.topjohnwu.magisk.core.utils.unzip
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import java.io.File
|
import java.io.File
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.tasks
|
package com.topjohnwu.magisk.core.tasks
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -6,11 +6,13 @@ import android.os.Build
|
|||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.topjohnwu.magisk.Config
|
import androidx.core.net.toUri
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||||
import com.topjohnwu.magisk.di.Protected
|
import com.topjohnwu.magisk.di.Protected
|
||||||
import com.topjohnwu.magisk.extensions.*
|
import com.topjohnwu.magisk.extensions.*
|
||||||
|
import com.topjohnwu.magisk.net.Networking
|
||||||
import com.topjohnwu.signing.SignBoot
|
import com.topjohnwu.signing.SignBoot
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
@ -34,10 +36,10 @@ import java.util.zip.ZipInputStream
|
|||||||
|
|
||||||
abstract class MagiskInstaller {
|
abstract class MagiskInstaller {
|
||||||
|
|
||||||
protected lateinit var srcBoot: String
|
|
||||||
protected lateinit var destFile: File
|
|
||||||
protected lateinit var installDir: File
|
protected lateinit var installDir: File
|
||||||
protected lateinit var zipUri: Uri
|
private lateinit var srcBoot: String
|
||||||
|
private lateinit var destFile: File
|
||||||
|
private lateinit var zipUri: Uri
|
||||||
|
|
||||||
private val console: MutableList<String>
|
private val console: MutableList<String>
|
||||||
private val logs: MutableList<String>
|
private val logs: MutableList<String>
|
||||||
@ -60,7 +62,7 @@ abstract class MagiskInstaller {
|
|||||||
installDir.mkdirs()
|
installDir.mkdirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun findImage(): Boolean {
|
private fun findImage(): Boolean {
|
||||||
srcBoot = "find_boot_image; echo \"\$BOOTIMAGE\"".fsh()
|
srcBoot = "find_boot_image; echo \"\$BOOTIMAGE\"".fsh()
|
||||||
if (srcBoot.isEmpty()) {
|
if (srcBoot.isEmpty()) {
|
||||||
console.add("! Unable to detect target image")
|
console.add("! Unable to detect target image")
|
||||||
@ -70,7 +72,7 @@ abstract class MagiskInstaller {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun findSecondaryImage(): Boolean {
|
private fun findSecondaryImage(): Boolean {
|
||||||
val slot = "echo \$SLOT".fsh()
|
val slot = "echo \$SLOT".fsh()
|
||||||
val target = if (slot == "_a") "_b" else "_a"
|
val target = if (slot == "_a") "_b" else "_a"
|
||||||
console.add("- Target slot: $target")
|
console.add("- Target slot: $target")
|
||||||
@ -87,7 +89,7 @@ abstract class MagiskInstaller {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun extractZip(): Boolean {
|
private fun extractZip(): Boolean {
|
||||||
val arch: String
|
val arch: String
|
||||||
arch = if (Build.VERSION.SDK_INT >= 21) {
|
arch = if (Build.VERSION.SDK_INT >= 21) {
|
||||||
val abis = listOf(*Build.SUPPORTED_ABIS)
|
val abis = listOf(*Build.SUPPORTED_ABIS)
|
||||||
@ -208,7 +210,7 @@ abstract class MagiskInstaller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun handleFile(uri: Uri): Boolean {
|
private fun handleFile(uri: Uri): Boolean {
|
||||||
try {
|
try {
|
||||||
context.readUri(uri).buffered().use {
|
context.readUri(uri).buffered().use {
|
||||||
it.mark(500)
|
it.mark(500)
|
||||||
@ -238,7 +240,7 @@ abstract class MagiskInstaller {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun patchBoot(): Boolean {
|
private fun patchBoot(): Boolean {
|
||||||
var isSigned = false
|
var isSigned = false
|
||||||
try {
|
try {
|
||||||
SuFileInputStream(srcBoot).use {
|
SuFileInputStream(srcBoot).use {
|
||||||
@ -284,7 +286,7 @@ abstract class MagiskInstaller {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun flashBoot(): Boolean {
|
private fun flashBoot(): Boolean {
|
||||||
if (!"direct_install $installDir $srcBoot".sh().isSuccess)
|
if (!"direct_install $installDir $srcBoot".sh().isSuccess)
|
||||||
return false
|
return false
|
||||||
arrayOf(
|
arrayOf(
|
||||||
@ -294,7 +296,7 @@ abstract class MagiskInstaller {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun storeBoot(): Boolean {
|
private fun storeBoot(): Boolean {
|
||||||
val patched = SuFile.open(installDir, "new-boot.img")
|
val patched = SuFile.open(installDir, "new-boot.img")
|
||||||
try {
|
try {
|
||||||
val os = tarOut?.let {
|
val os = tarOut?.let {
|
||||||
@ -320,7 +322,7 @@ abstract class MagiskInstaller {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun postOTA(): Boolean {
|
private fun postOTA(): Boolean {
|
||||||
val bootctl = SuFile("/data/adb/bootctl")
|
val bootctl = SuFile("/data/adb/bootctl")
|
||||||
try {
|
try {
|
||||||
withStreams(service.fetchBootctl().blockingGet().byteStream(), bootctl.suOutputStream()) {
|
withStreams(service.fetchBootctl().blockingGet().byteStream(), bootctl.suOutputStream()) {
|
||||||
@ -345,6 +347,28 @@ abstract class MagiskInstaller {
|
|||||||
private fun String.fsh() = ShellUtils.fastCmd(this)
|
private fun String.fsh() = ShellUtils.fastCmd(this)
|
||||||
private fun Array<String>.fsh() = ShellUtils.fastCmd(*this)
|
private fun Array<String>.fsh() = ShellUtils.fastCmd(*this)
|
||||||
|
|
||||||
|
protected fun doPatchFile(patchFile: Uri) =
|
||||||
|
extractZip() && handleFile(patchFile) && patchBoot() && storeBoot()
|
||||||
|
|
||||||
|
protected fun direct() = findImage() && extractZip() && patchBoot() && flashBoot()
|
||||||
|
|
||||||
|
protected fun secondSlot() =
|
||||||
|
findSecondaryImage() && extractZip() && patchBoot() && flashBoot() && postOTA()
|
||||||
|
|
||||||
|
protected fun fixEnv(): Boolean {
|
||||||
|
val context = get<Context>()
|
||||||
|
val zip: File = context.cachedFile("magisk.zip")
|
||||||
|
|
||||||
|
installDir = SuFile("/data/adb/magisk")
|
||||||
|
Shell.su("rm -rf /data/adb/magisk/*").exec()
|
||||||
|
|
||||||
|
if (!ShellUtils.checkSum("MD5", zip, Info.remote.magisk.md5))
|
||||||
|
Networking.get(Info.remote.magisk.link).execForFile(zip)
|
||||||
|
|
||||||
|
zipUri = zip.toUri()
|
||||||
|
return extractZip() && Shell.su("fix_env").exec().isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
protected abstract fun operations(): Boolean
|
protected abstract fun operations(): Boolean
|
||||||
|
|
@ -1,11 +1,11 @@
|
|||||||
package com.topjohnwu.magisk.tasks
|
package com.topjohnwu.magisk.core.tasks
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
import com.topjohnwu.magisk.data.database.RepoDao
|
import com.topjohnwu.magisk.data.database.RepoDao
|
||||||
import com.topjohnwu.magisk.data.network.GithubApiServices
|
import com.topjohnwu.magisk.data.network.GithubApiServices
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Flowable
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.Single
|
|
||||||
import io.reactivex.rxkotlin.toFlowable
|
import io.reactivex.rxkotlin.toFlowable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import se.ansman.kotshi.JsonSerializable
|
import se.ansman.kotshi.JsonSerializable
|
||||||
@ -19,18 +19,17 @@ class RepoUpdater(
|
|||||||
private val api: GithubApiServices,
|
private val api: GithubApiServices,
|
||||||
private val repoDB: RepoDao
|
private val repoDB: RepoDao
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private fun loadRepos(repos: List<GithubRepoInfo>, cached: MutableSet<String>) =
|
private fun loadRepos(repos: List<GithubRepoInfo>, cached: MutableSet<String>) =
|
||||||
repos.toFlowable().parallel().runOn(Schedulers.io()).map {
|
repos.toFlowable().parallel().runOn(Schedulers.io()).map {
|
||||||
// Skip submission
|
// Skip submission
|
||||||
if (it.id == "submission")
|
if (it.id == "submission")
|
||||||
return@map
|
return@map
|
||||||
(repoDB.getRepo(it.id)?.apply { cached.remove(it.id) } ?:
|
(repoDB.getRepo(it.id)?.apply { cached.remove(it.id) } ?:
|
||||||
Repo(it.id)).runCatching {
|
Repo(it.id)).runCatching {
|
||||||
update(it.pushDate)
|
update(it.pushDate)
|
||||||
repoDB.addRepo(this)
|
repoDB.addRepo(this)
|
||||||
}.getOrElse { Timber.e(it) }
|
}.getOrElse { Timber.e(it) }
|
||||||
}.sequential()
|
}.sequential()
|
||||||
|
|
||||||
private fun loadPage(
|
private fun loadPage(
|
||||||
cached: MutableSet<String>,
|
cached: MutableSet<String>,
|
||||||
@ -55,16 +54,16 @@ class RepoUpdater(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun forcedReload(cached: MutableSet<String>) =
|
private fun forcedReload(cached: MutableSet<String>) =
|
||||||
cached.toFlowable().parallel().runOn(Schedulers.io()).map {
|
cached.toFlowable().parallel().runOn(Schedulers.io()).map {
|
||||||
runCatching {
|
runCatching {
|
||||||
Repo(it).update()
|
Repo(it).update()
|
||||||
}.getOrElse { Timber.e(it) }
|
}.getOrElse { Timber.e(it) }
|
||||||
}.sequential()
|
}.sequential()
|
||||||
|
|
||||||
private fun String.trimEtag() = substring(indexOf('\"'), lastIndexOf('\"') + 1)
|
private fun String.trimEtag() = substring(indexOf('\"'), lastIndexOf('\"') + 1)
|
||||||
|
|
||||||
@Suppress("RedundantLambdaArrow")
|
@Suppress("RedundantLambdaArrow")
|
||||||
operator fun invoke(forced: Boolean = false) : Single<Unit> {
|
operator fun invoke(forced: Boolean = false) : Completable {
|
||||||
val cached = Collections.synchronizedSet(HashSet(repoDB.repoIDList))
|
val cached = Collections.synchronizedSet(HashSet(repoDB.repoIDList))
|
||||||
return loadPage(cached, etag = repoDB.etagKey).doOnComplete {
|
return loadPage(cached, etag = repoDB.etagKey).doOnComplete {
|
||||||
repoDB.removeRepos(cached)
|
repoDB.removeRepos(cached)
|
||||||
@ -76,16 +75,16 @@ class RepoUpdater(
|
|||||||
Timber.e(it)
|
Timber.e(it)
|
||||||
}
|
}
|
||||||
Flowable.empty()
|
Flowable.empty()
|
||||||
}.ignoreElements().toSingleDefault(Unit)
|
}.ignoreElements()
|
||||||
}
|
}
|
||||||
|
|
||||||
object CachedException : Exception()
|
object CachedException : Exception()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val dateFormat: SimpleDateFormat =
|
private val dateFormat: SimpleDateFormat =
|
||||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
|
||||||
timeZone = TimeZone.getTimeZone("UTC")
|
timeZone = TimeZone.getTimeZone("UTC")
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSerializable
|
@JsonSerializable
|
||||||
data class GithubRepoInfo(
|
data class GithubRepoInfo(
|
@ -1,11 +1,11 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import androidx.biometric.BiometricManager
|
import androidx.biometric.BiometricManager
|
||||||
import androidx.biometric.BiometricPrompt
|
import androidx.biometric.BiometricPrompt
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.get
|
import org.koin.core.get
|
||||||
|
|
@ -1,11 +1,11 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Base64OutputStream
|
import android.util.Base64OutputStream
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.utils.PatchAPK.ALPHANUM
|
||||||
import com.topjohnwu.magisk.di.koinModules
|
import com.topjohnwu.magisk.di.koinModules
|
||||||
import com.topjohnwu.magisk.utils.PatchAPK.ALPHANUM
|
|
||||||
import com.topjohnwu.signing.CryptoUtils.readCertificate
|
import com.topjohnwu.signing.CryptoUtils.readCertificate
|
||||||
import com.topjohnwu.signing.CryptoUtils.readPrivateKey
|
import com.topjohnwu.signing.CryptoUtils.readPrivateKey
|
||||||
import com.topjohnwu.superuser.internal.InternalUtils
|
import com.topjohnwu.superuser.internal.InternalUtils
|
||||||
@ -50,10 +50,14 @@ class Keygen: CertKeyProvider {
|
|||||||
|
|
||||||
private val provider: CertKeyProvider
|
private val provider: CertKeyProvider
|
||||||
|
|
||||||
inner class KeyStoreProvider : CertKeyProvider {
|
inner class KeyStoreProvider :
|
||||||
|
CertKeyProvider {
|
||||||
private val ks by lazy { init() }
|
private val ks by lazy { init() }
|
||||||
override val cert by lazy { ks.getCertificate(ALIAS) as X509Certificate }
|
override val cert by lazy { ks.getCertificate(ALIAS) as X509Certificate }
|
||||||
override val key by lazy { ks.getKey(ALIAS, PASSWORD) as PrivateKey }
|
override val key by lazy { ks.getKey(
|
||||||
|
ALIAS,
|
||||||
|
PASSWORD
|
||||||
|
) as PrivateKey }
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestProvider : CertKeyProvider {
|
class TestProvider : CertKeyProvider {
|
||||||
@ -113,8 +117,12 @@ class Keygen: CertKeyProvider {
|
|||||||
if (raw.isEmpty()) {
|
if (raw.isEmpty()) {
|
||||||
ks.load(null)
|
ks.load(null)
|
||||||
} else {
|
} else {
|
||||||
GZIPInputStream(Base64.decode(raw, BASE64_FLAG).inputStream()).use {
|
GZIPInputStream(Base64.decode(raw,
|
||||||
ks.load(it, PASSWORD)
|
BASE64_FLAG
|
||||||
|
).inputStream()).use {
|
||||||
|
ks.load(it,
|
||||||
|
PASSWORD
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,10 +139,16 @@ class Keygen: CertKeyProvider {
|
|||||||
val cert = JcaX509CertificateConverter().getCertificate(builder.build(signer))
|
val cert = JcaX509CertificateConverter().getCertificate(builder.build(signer))
|
||||||
|
|
||||||
// Store them into keystore
|
// Store them into keystore
|
||||||
ks.setKeyEntry(ALIAS, kp.private, PASSWORD, arrayOf(cert))
|
ks.setKeyEntry(
|
||||||
|
ALIAS, kp.private,
|
||||||
|
PASSWORD, arrayOf(cert))
|
||||||
val bytes = ByteArrayOutputStream()
|
val bytes = ByteArrayOutputStream()
|
||||||
GZIPOutputStream(Base64OutputStream(bytes, BASE64_FLAG)).use {
|
GZIPOutputStream(Base64OutputStream(bytes,
|
||||||
ks.store(it, PASSWORD)
|
BASE64_FLAG
|
||||||
|
)).use {
|
||||||
|
ks.store(it,
|
||||||
|
PASSWORD
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Config.keyStoreRaw = bytes.toString("UTF-8")
|
Config.keyStoreRaw = bytes.toString("UTF-8")
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
@file:Suppress("DEPRECATION")
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.ResourceMgr
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.ResourceMgr
|
||||||
import com.topjohnwu.magisk.extensions.langTagToLocale
|
import com.topjohnwu.magisk.extensions.langTagToLocale
|
||||||
import com.topjohnwu.magisk.extensions.toLangTag
|
import com.topjohnwu.magisk.extensions.toLangTag
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
@ -1,15 +1,20 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build.VERSION.SDK_INT
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||||
import com.topjohnwu.magisk.extensions.DynamicClassLoader
|
import com.topjohnwu.magisk.extensions.DynamicClassLoader
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.subscribeK
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.extensions.writeTo
|
import com.topjohnwu.magisk.extensions.writeTo
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.core.view.Notifications
|
||||||
import com.topjohnwu.signing.JarMap
|
import com.topjohnwu.signing.JarMap
|
||||||
import com.topjohnwu.signing.SignAPK
|
import com.topjohnwu.signing.SignAPK
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import java.io.FilterInputStream
|
import java.io.FilterInputStream
|
||||||
@ -41,4 +41,4 @@ class ProgressInputStream(
|
|||||||
}
|
}
|
||||||
return sz
|
return sz
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import com.topjohnwu.magisk.extensions.rawResource
|
import com.topjohnwu.magisk.extensions.rawResource
|
||||||
import com.topjohnwu.magisk.wrap
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
interface SafetyNetHelper {
|
interface SafetyNetHelper {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -7,10 +7,10 @@ import android.net.Uri
|
|||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.*
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.model.update.UpdateCheckService
|
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -62,7 +62,10 @@ object Utils {
|
|||||||
if (intent.resolveActivity(context.packageManager) != null) {
|
if (intent.resolveActivity(context.packageManager) != null) {
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.open_link_failed_toast, Toast.LENGTH_SHORT)
|
toast(
|
||||||
|
R.string.open_link_failed_toast,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.utils
|
package com.topjohnwu.magisk.core.utils
|
||||||
|
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
import com.topjohnwu.superuser.io.SuFileOutputStream
|
import com.topjohnwu.superuser.io.SuFileOutputStream
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.view
|
package com.topjohnwu.magisk.core.view
|
||||||
|
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
@ -9,13 +9,12 @@ import android.os.Build.VERSION.SDK_INT
|
|||||||
import androidx.core.app.TaskStackBuilder
|
import androidx.core.app.TaskStackBuilder
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.graphics.drawable.toIcon
|
import androidx.core.graphics.drawable.toIcon
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
|
import com.topjohnwu.magisk.core.*
|
||||||
import com.topjohnwu.magisk.Const.ID.UPDATE_NOTIFICATION_CHANNEL
|
import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
|
||||||
|
import com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.extensions.getBitmap
|
import com.topjohnwu.magisk.extensions.getBitmap
|
||||||
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
|
||||||
import com.topjohnwu.magisk.ui.SplashActivity
|
|
||||||
|
|
||||||
object Notifications {
|
object Notifications {
|
||||||
|
|
||||||
@ -52,10 +51,13 @@ object Notifications {
|
|||||||
val stackBuilder = TaskStackBuilder.create(context)
|
val stackBuilder = TaskStackBuilder.create(context)
|
||||||
stackBuilder.addParentStack(SplashActivity::class.java.cmp(context.packageName))
|
stackBuilder.addParentStack(SplashActivity::class.java.cmp(context.packageName))
|
||||||
stackBuilder.addNextIntent(intent)
|
stackBuilder.addNextIntent(intent)
|
||||||
val pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
|
val pendingIntent = stackBuilder.getPendingIntent(
|
||||||
|
Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
||||||
val builder = updateBuilder(context)
|
val builder = updateBuilder(
|
||||||
|
context
|
||||||
|
)
|
||||||
.setContentTitle(context.getString(R.string.magisk_update_title))
|
.setContentTitle(context.getString(R.string.magisk_update_title))
|
||||||
.setContentText(context.getString(R.string.manager_download_install))
|
.setContentText(context.getString(R.string.manager_download_install))
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
@ -72,7 +74,9 @@ object Notifications {
|
|||||||
val pendingIntent = PendingIntent.getBroadcast(context,
|
val pendingIntent = PendingIntent.getBroadcast(context,
|
||||||
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
||||||
val builder = updateBuilder(context)
|
val builder = updateBuilder(
|
||||||
|
context
|
||||||
|
)
|
||||||
.setContentTitle(context.getString(R.string.manager_update_title))
|
.setContentTitle(context.getString(R.string.manager_update_title))
|
||||||
.setContentText(context.getString(R.string.manager_download_install))
|
.setContentText(context.getString(R.string.manager_download_install))
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
@ -87,7 +91,9 @@ object Notifications {
|
|||||||
val pendingIntent = PendingIntent.getBroadcast(context,
|
val pendingIntent = PendingIntent.getBroadcast(context,
|
||||||
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
||||||
val builder = updateBuilder(context)
|
val builder = updateBuilder(
|
||||||
|
context
|
||||||
|
)
|
||||||
.setContentTitle(context.getString(R.string.dtbo_patched_title))
|
.setContentTitle(context.getString(R.string.dtbo_patched_title))
|
||||||
.setContentText(context.getString(R.string.dtbo_patched_reboot))
|
.setContentText(context.getString(R.string.dtbo_patched_reboot))
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.view
|
package com.topjohnwu.magisk.core.view
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -10,17 +10,18 @@ import androidx.annotation.RequiresApi
|
|||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.graphics.drawable.toAdaptiveIcon
|
import androidx.core.graphics.drawable.toAdaptiveIcon
|
||||||
import androidx.core.graphics.drawable.toIcon
|
import androidx.core.graphics.drawable.toIcon
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.*
|
||||||
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.magisk.extensions.getBitmap
|
import com.topjohnwu.magisk.extensions.getBitmap
|
||||||
import com.topjohnwu.magisk.ui.SplashActivity
|
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
|
||||||
|
|
||||||
object Shortcuts {
|
object Shortcuts {
|
||||||
|
|
||||||
fun setup(context: Context) {
|
fun setup(context: Context) {
|
||||||
if (Build.VERSION.SDK_INT >= 25) {
|
if (Build.VERSION.SDK_INT >= 25) {
|
||||||
val manager = context.getSystemService<ShortcutManager>()
|
val manager = context.getSystemService<ShortcutManager>()
|
||||||
manager?.dynamicShortcuts = getShortCuts(context)
|
manager?.dynamicShortcuts =
|
||||||
|
getShortCuts(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ package com.topjohnwu.magisk.data.database
|
|||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
|
|
||||||
interface RepoBase {
|
interface RepoBase {
|
||||||
|
|
||||||
@ -64,4 +64,4 @@ interface RepoByNameDao : RepoBase {
|
|||||||
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
|
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.data.database
|
package com.topjohnwu.magisk.data.database
|
||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
|
|
||||||
@Database(version = 6, entities = [Repo::class, RepoEtag::class])
|
@Database(version = 6, entities = [Repo::class, RepoEtag::class])
|
||||||
abstract class RepoDatabase : RoomDatabase() {
|
abstract class RepoDatabase : RoomDatabase() {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.data.network
|
package com.topjohnwu.magisk.data.network
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.model.entity.UpdateInfo
|
import com.topjohnwu.magisk.core.tasks.GithubRepoInfo
|
||||||
import com.topjohnwu.magisk.tasks.GithubRepoInfo
|
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||||
import io.reactivex.Flowable
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
@ -78,4 +78,4 @@ interface GithubApiServices {
|
|||||||
@Query("sort") sort: String = "pushed",
|
@Query("sort") sort: String = "pushed",
|
||||||
@Query("per_page") count: Int = 100): Flowable<Result<List<GithubRepoInfo>>>
|
@Query("per_page") count: Int = 100): Flowable<Result<List<GithubRepoInfo>>>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.data.repository
|
package com.topjohnwu.magisk.data.repository
|
||||||
|
|
||||||
import com.topjohnwu.magisk.data.database.SettingsDao
|
import com.topjohnwu.magisk.core.magiskdb.SettingsDao
|
||||||
import com.topjohnwu.magisk.data.database.StringDao
|
import com.topjohnwu.magisk.core.magiskdb.StringDao
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.data.repository
|
package com.topjohnwu.magisk.data.repository
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.data.database.SuLogDao
|
import com.topjohnwu.magisk.data.database.SuLogDao
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskLog
|
import com.topjohnwu.magisk.model.entity.MagiskLog
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.data.repository
|
package com.topjohnwu.magisk.data.repository
|
||||||
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||||
import com.topjohnwu.magisk.extensions.getLabel
|
import com.topjohnwu.magisk.extensions.getLabel
|
||||||
import com.topjohnwu.magisk.extensions.packageName
|
import com.topjohnwu.magisk.extensions.packageName
|
||||||
@ -24,7 +24,8 @@ class MagiskRepository(
|
|||||||
Config.Value.BETA_CHANNEL -> apiRaw.fetchBetaUpdate()
|
Config.Value.BETA_CHANNEL -> apiRaw.fetchBetaUpdate()
|
||||||
Config.Value.CANARY_CHANNEL -> apiRaw.fetchCanaryUpdate()
|
Config.Value.CANARY_CHANNEL -> apiRaw.fetchCanaryUpdate()
|
||||||
Config.Value.CANARY_DEBUG_CHANNEL -> apiRaw.fetchCanaryDebugUpdate()
|
Config.Value.CANARY_DEBUG_CHANNEL -> apiRaw.fetchCanaryDebugUpdate()
|
||||||
Config.Value.CUSTOM_CHANNEL -> apiRaw.fetchCustomUpdate(Config.customChannelUrl)
|
Config.Value.CUSTOM_CHANNEL -> apiRaw.fetchCustomUpdate(
|
||||||
|
Config.customChannelUrl)
|
||||||
else -> throw IllegalArgumentException()
|
else -> throw IllegalArgumentException()
|
||||||
}.flatMap {
|
}.flatMap {
|
||||||
// If remote version is lower than current installed, try switching to beta
|
// If remote version is lower than current installed, try switching to beta
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.data.repository
|
package com.topjohnwu.magisk.data.repository
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
|
||||||
|
|
||||||
class StringRepository(
|
class StringRepository(
|
||||||
private val api: GithubRawServices
|
private val api: GithubRawServices
|
||||||
@ -12,4 +12,4 @@ class StringRepository(
|
|||||||
fun getMetadata(repo: Repo) = api.fetchModuleInfo(repo.id, "module.prop")
|
fun getMetadata(repo: Repo) = api.fetchModuleInfo(repo.id, "module.prop")
|
||||||
|
|
||||||
fun getReadme(repo: Repo) = api.fetchModuleInfo(repo.id, "README.md")
|
fun getReadme(repo: Repo) = api.fetchModuleInfo(repo.id, "README.md")
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,12 @@ package com.topjohnwu.magisk.di
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import com.topjohnwu.magisk.data.database.*
|
import com.topjohnwu.magisk.core.magiskdb.PolicyDao
|
||||||
import com.topjohnwu.magisk.tasks.RepoUpdater
|
import com.topjohnwu.magisk.core.magiskdb.SettingsDao
|
||||||
|
import com.topjohnwu.magisk.core.magiskdb.StringDao
|
||||||
|
import com.topjohnwu.magisk.core.tasks.RepoUpdater
|
||||||
|
import com.topjohnwu.magisk.data.database.RepoDatabase
|
||||||
|
import com.topjohnwu.magisk.data.database.SuLogDatabase
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||||||
import com.squareup.moshi.JsonAdapter
|
import com.squareup.moshi.JsonAdapter
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.data.network.GithubApiServices
|
import com.topjohnwu.magisk.data.network.GithubApiServices
|
||||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||||
import com.topjohnwu.magisk.net.Networking
|
import com.topjohnwu.magisk.net.Networking
|
||||||
|
@ -28,11 +28,11 @@ import androidx.appcompat.content.res.AppCompatResources
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.net.toFile
|
import androidx.core.net.toFile
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.FileProvider
|
import com.topjohnwu.magisk.FileProvider
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.magisk.utils.currentLocale
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -317,7 +317,9 @@ fun Context.hasPermissions(vararg permissions: String) = permissions.all {
|
|||||||
ContextCompat.checkSelfPermission(this, it) == PERMISSION_GRANTED
|
ContextCompat.checkSelfPermission(this, it) == PERMISSION_GRANTED
|
||||||
}
|
}
|
||||||
|
|
||||||
private val securityLevelFormatter get() = SimpleDateFormat("yyyy-MM-dd", currentLocale)
|
private val securityLevelFormatter get() = SimpleDateFormat("yyyy-MM-dd",
|
||||||
|
currentLocale
|
||||||
|
)
|
||||||
|
|
||||||
/** Friendly reminder to seek newer roms or install oem updates. */
|
/** Friendly reminder to seek newer roms or install oem updates. */
|
||||||
val isDeviceSecure: Boolean
|
val isDeviceSecure: Boolean
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.extensions
|
package com.topjohnwu.magisk.extensions
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.io.SuFileInputStream
|
import com.topjohnwu.superuser.io.SuFileInputStream
|
||||||
import com.topjohnwu.superuser.io.SuFileOutputStream
|
import com.topjohnwu.superuser.io.SuFileOutputStream
|
||||||
@ -13,4 +13,4 @@ fun reboot(reason: String = if (Info.recovery) "recovery" else "") {
|
|||||||
fun File.suOutputStream() = SuFileOutputStream(this)
|
fun File.suOutputStream() = SuFileOutputStream(this)
|
||||||
fun File.suInputStream() = SuFileInputStream(this)
|
fun File.suInputStream() = SuFileInputStream(this)
|
||||||
|
|
||||||
val hasRoot get() = Shell.rootAccess()
|
val hasRoot get() = Shell.rootAccess()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.extensions
|
package com.topjohnwu.magisk.extensions
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.currentLocale
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.ParseException
|
import java.text.ParseException
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@ -14,10 +14,18 @@ fun String.toTime(format: DateFormat) = try {
|
|||||||
-1L
|
-1L
|
||||||
}
|
}
|
||||||
|
|
||||||
val timeFormatFull by lazy { SimpleDateFormat("yyyy/MM/dd_HH:mm:ss", currentLocale) }
|
val timeFormatFull by lazy { SimpleDateFormat("yyyy/MM/dd_HH:mm:ss",
|
||||||
val timeFormatStandard by lazy { SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", currentLocale) }
|
currentLocale
|
||||||
val timeFormatMedium by lazy { DateFormat.getDateInstance(DateFormat.MEDIUM, currentLocale) }
|
) }
|
||||||
val timeFormatTime by lazy { SimpleDateFormat("h:mm a", currentLocale) }
|
val timeFormatStandard by lazy { SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||||
|
currentLocale
|
||||||
|
) }
|
||||||
|
val timeFormatMedium by lazy { DateFormat.getDateInstance(DateFormat.MEDIUM,
|
||||||
|
currentLocale
|
||||||
|
) }
|
||||||
|
val timeFormatTime by lazy { SimpleDateFormat("h:mm a",
|
||||||
|
currentLocale
|
||||||
|
) }
|
||||||
val timeDateFormat by lazy {
|
val timeDateFormat by lazy {
|
||||||
DateFormat.getDateTimeInstance(
|
DateFormat.getDateTimeInstance(
|
||||||
DateFormat.DEFAULT,
|
DateFormat.DEFAULT,
|
||||||
|
@ -6,22 +6,22 @@ import android.content.pm.ActivityInfo
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.intent
|
||||||
import com.topjohnwu.magisk.databinding.ActivityFlashBinding
|
import com.topjohnwu.magisk.databinding.ActivityFlashBinding
|
||||||
import com.topjohnwu.magisk.extensions.snackbar
|
import com.topjohnwu.magisk.extensions.snackbar
|
||||||
import com.topjohnwu.magisk.intent
|
|
||||||
import com.topjohnwu.magisk.model.events.BackPressEvent
|
import com.topjohnwu.magisk.model.events.BackPressEvent
|
||||||
import com.topjohnwu.magisk.model.events.PermissionEvent
|
import com.topjohnwu.magisk.model.events.PermissionEvent
|
||||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.ui.base.BaseUIActivity
|
||||||
|
import com.topjohnwu.magisk.core.view.Notifications
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class FlashActivity : BaseActivity<FlashViewModel, ActivityFlashBinding>() {
|
open class FlashActivity : BaseUIActivity<FlashViewModel, ActivityFlashBinding>() {
|
||||||
|
|
||||||
override val layoutRes: Int = R.layout.activity_flash
|
override val layoutRes: Int = R.layout.activity_flash
|
||||||
override val themeRes: Int = R.style.MagiskTheme_Flashing
|
override val themeRes: Int = R.style.MagiskTheme_Flashing
|
||||||
|
@ -8,10 +8,9 @@ import android.os.Handler
|
|||||||
import androidx.core.os.postDelayed
|
import androidx.core.os.postDelayed
|
||||||
import androidx.databinding.ObservableArrayList
|
import androidx.databinding.ObservableArrayList
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.BaseViewModel
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.extensions.*
|
import com.topjohnwu.magisk.extensions.*
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.ConsoleRvItem
|
import com.topjohnwu.magisk.model.entity.recycler.ConsoleRvItem
|
||||||
@ -19,6 +18,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
|
|||||||
import com.topjohnwu.magisk.model.flash.FlashResultListener
|
import com.topjohnwu.magisk.model.flash.FlashResultListener
|
||||||
import com.topjohnwu.magisk.model.flash.Flashing
|
import com.topjohnwu.magisk.model.flash.Flashing
|
||||||
import com.topjohnwu.magisk.model.flash.Patching
|
import com.topjohnwu.magisk.model.flash.Patching
|
||||||
|
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||||
import com.topjohnwu.magisk.utils.DiffObservableList
|
import com.topjohnwu.magisk.utils.DiffObservableList
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
|
@ -6,16 +6,16 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||||
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler.REQUEST
|
||||||
import com.topjohnwu.magisk.databinding.ActivityRequestBinding
|
import com.topjohnwu.magisk.databinding.ActivityRequestBinding
|
||||||
import com.topjohnwu.magisk.model.events.DieEvent
|
import com.topjohnwu.magisk.model.events.DieEvent
|
||||||
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||||
import com.topjohnwu.magisk.utils.SuHandler
|
import com.topjohnwu.magisk.ui.base.BaseUIActivity
|
||||||
import com.topjohnwu.magisk.utils.SuHandler.REQUEST
|
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
open class SuRequestActivity : BaseActivity<SuRequestViewModel, ActivityRequestBinding>() {
|
open class SuRequestActivity : BaseUIActivity<SuRequestViewModel, ActivityRequestBinding>() {
|
||||||
|
|
||||||
override val layoutRes: Int = R.layout.activity_request
|
override val layoutRes: Int = R.layout.activity_request
|
||||||
override val themeRes: Int = R.style.MagiskTheme_SU
|
override val themeRes: Int = R.style.MagiskTheme_SU
|
||||||
@ -36,7 +36,11 @@ open class SuRequestActivity : BaseActivity<SuRequestViewModel, ActivityRequestB
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun runHandler(action: String?) {
|
fun runHandler(action: String?) {
|
||||||
SuHandler(this, action, intent.extras)
|
SuCallbackHandler(
|
||||||
|
this,
|
||||||
|
action,
|
||||||
|
intent.extras
|
||||||
|
)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,41 +6,36 @@ import android.content.pm.PackageManager
|
|||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.BaseViewModel
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.data.database.PolicyDao
|
import com.topjohnwu.magisk.core.magiskdb.PolicyDao
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.ALLOW
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.DENY
|
||||||
|
import com.topjohnwu.magisk.core.su.SuRequestHandler
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.extensions.now
|
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem
|
import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem
|
||||||
import com.topjohnwu.magisk.model.entity.toPolicy
|
|
||||||
import com.topjohnwu.magisk.model.events.DieEvent
|
import com.topjohnwu.magisk.model.events.DieEvent
|
||||||
import com.topjohnwu.magisk.utils.BiometricHelper
|
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
import com.topjohnwu.magisk.utils.DiffObservableList
|
import com.topjohnwu.magisk.utils.DiffObservableList
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.magisk.utils.SuConnector
|
|
||||||
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
|
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
|
||||||
import me.tatarka.bindingcollectionadapter2.ItemBinding
|
import me.tatarka.bindingcollectionadapter2.ItemBinding
|
||||||
import timber.log.Timber
|
import java.util.concurrent.TimeUnit.SECONDS
|
||||||
import java.io.IOException
|
|
||||||
import java.util.concurrent.TimeUnit.*
|
|
||||||
|
|
||||||
class SuRequestViewModel(
|
class SuRequestViewModel(
|
||||||
private val packageManager: PackageManager,
|
private val pm: PackageManager,
|
||||||
private val policyDB: PolicyDao,
|
private val policyDB: PolicyDao,
|
||||||
private val timeoutPrefs: SharedPreferences,
|
private val timeoutPrefs: SharedPreferences,
|
||||||
private val resources: Resources
|
private val res: Resources
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
val icon = KObservableField<Drawable?>(null)
|
val icon = KObservableField<Drawable?>(null)
|
||||||
val title = KObservableField("")
|
val title = KObservableField("")
|
||||||
val packageName = KObservableField("")
|
val packageName = KObservableField("")
|
||||||
|
|
||||||
val denyText = KObservableField(resources.getString(R.string.deny))
|
val denyText = KObservableField(res.getString(R.string.deny))
|
||||||
val warningText = KObservableField<CharSequence>(resources.getString(R.string.su_warning))
|
val warningText = KObservableField<CharSequence>(res.getString(R.string.su_warning))
|
||||||
|
|
||||||
val selectedItemPosition = KObservableField(0)
|
val selectedItemPosition = KObservableField(0)
|
||||||
|
|
||||||
@ -54,130 +49,74 @@ class SuRequestViewModel(
|
|||||||
setItems(items)
|
setItems(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cancelTasks = mutableListOf<() -> Unit>()
|
private val handler = Handler()
|
||||||
|
|
||||||
private lateinit var timer: CountDownTimer
|
|
||||||
private lateinit var policy: MagiskPolicy
|
|
||||||
private lateinit var connector: SuConnector
|
|
||||||
|
|
||||||
private fun cancelTimer() {
|
|
||||||
timer.cancel()
|
|
||||||
denyText.value = resources.getString(R.string.deny)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun grantPressed() {
|
fun grantPressed() {
|
||||||
cancelTimer()
|
handler.cancelTimer()
|
||||||
if (BiometricHelper.isEnabled) {
|
if (BiometricHelper.isEnabled) {
|
||||||
withView {
|
withView {
|
||||||
BiometricHelper.authenticate(this) {
|
BiometricHelper.authenticate(this) {
|
||||||
handleAction(MagiskPolicy.ALLOW)
|
handler.respond(ALLOW)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleAction(MagiskPolicy.ALLOW)
|
handler.respond(ALLOW)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun denyPressed() {
|
fun denyPressed() {
|
||||||
handleAction(MagiskPolicy.DENY)
|
handler.respond(DENY)
|
||||||
timer.cancel()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun spinnerTouched(): Boolean {
|
fun spinnerTouched(): Boolean {
|
||||||
cancelTimer()
|
handler.cancelTimer()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleRequest(intent: Intent): Boolean {
|
fun handleRequest(intent: Intent): Boolean {
|
||||||
val socketName = intent.getStringExtra("socket") ?: return false
|
return handler.start(intent)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
private inner class Handler : SuRequestHandler(pm, policyDB) {
|
||||||
connector = Connector(socketName)
|
|
||||||
val map = connector.readRequest()
|
fun respond(action: Int) {
|
||||||
val uid = map["uid"]?.toIntOrNull() ?: return false
|
val pos = selectedItemPosition.value
|
||||||
policy = uid.toPolicy(packageManager)
|
timeoutPrefs.edit().putInt(policy.packageName, pos).apply()
|
||||||
} catch (e: Exception) {
|
respond(action, Config.Value.TIMEOUT_LIST[pos])
|
||||||
Timber.e(e)
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never allow com.topjohnwu.magisk (could be malware)
|
fun cancelTimer() {
|
||||||
if (policy.packageName == BuildConfig.APPLICATION_ID)
|
timer.cancel()
|
||||||
return false
|
denyText.value = res.getString(R.string.deny)
|
||||||
|
}
|
||||||
|
|
||||||
when (Config.suAutoReponse) {
|
override fun onStart() {
|
||||||
Config.Value.SU_AUTO_DENY -> {
|
res.getStringArray(R.array.allow_timeout)
|
||||||
handleAction(MagiskPolicy.DENY, 0)
|
.map { SpinnerRvItem(it) }
|
||||||
return true
|
.let { items.update(it) }
|
||||||
}
|
|
||||||
Config.Value.SU_AUTO_ALLOW -> {
|
icon.value = policy.applicationInfo.loadIcon(pm)
|
||||||
handleAction(MagiskPolicy.ALLOW, 0)
|
title.value = policy.appName
|
||||||
return true
|
packageName.value = policy.packageName
|
||||||
|
selectedItemPosition.value = timeoutPrefs.getInt(policy.packageName, 0)
|
||||||
|
|
||||||
|
// Override timer
|
||||||
|
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
||||||
|
timer = object : CountDownTimer(millis, 1000) {
|
||||||
|
override fun onTick(remains: Long) {
|
||||||
|
denyText.value = "${res.getString(R.string.deny)} (${remains / 1000})"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
denyText.value = res.getString(R.string.deny)
|
||||||
|
respond(DENY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showUI()
|
override fun onRespond() {
|
||||||
return true
|
// Kill activity after response
|
||||||
}
|
DieEvent().publish()
|
||||||
|
|
||||||
private fun showUI() {
|
|
||||||
resources.getStringArray(R.array.allow_timeout)
|
|
||||||
.map { SpinnerRvItem(it) }
|
|
||||||
.let { items.update(it) }
|
|
||||||
|
|
||||||
icon.value = policy.applicationInfo.loadIcon(packageManager)
|
|
||||||
title.value = policy.appName
|
|
||||||
packageName.value = policy.packageName
|
|
||||||
selectedItemPosition.value = timeoutPrefs.getInt(policy.packageName, 0)
|
|
||||||
|
|
||||||
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
|
||||||
timer = object : CountDownTimer(millis, 1000) {
|
|
||||||
override fun onTick(remains: Long) {
|
|
||||||
denyText.value = "${resources.getString(R.string.deny)} (${remains / 1000})"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFinish() {
|
|
||||||
denyText.value = resources.getString(R.string.deny)
|
|
||||||
handleAction(MagiskPolicy.DENY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timer.start()
|
|
||||||
cancelTasks.add { cancelTimer() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleAction() {
|
|
||||||
connector.response()
|
|
||||||
cancelTasks.forEach { it() }
|
|
||||||
DieEvent().publish()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleAction(action: Int) {
|
|
||||||
val pos = selectedItemPosition.value
|
|
||||||
timeoutPrefs.edit().putInt(policy.packageName, pos).apply()
|
|
||||||
handleAction(action, Config.Value.TIMEOUT_LIST[pos])
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleAction(action: Int, time: Int) {
|
|
||||||
val until = if (time > 0)
|
|
||||||
MILLISECONDS.toSeconds(now) + MINUTES.toSeconds(time.toLong())
|
|
||||||
else
|
|
||||||
time.toLong()
|
|
||||||
|
|
||||||
policy.policy = action
|
|
||||||
policy.until = until
|
|
||||||
policy.uid = policy.uid % 100000 + Const.USER_ID * 100000
|
|
||||||
|
|
||||||
if (until >= 0)
|
|
||||||
policyDB.update(policy).blockingAwait()
|
|
||||||
|
|
||||||
handleAction()
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class Connector @Throws(Exception::class)
|
|
||||||
internal constructor(name: String) : SuConnector(name) {
|
|
||||||
@Throws(IOException::class)
|
|
||||||
override fun onResponse() {
|
|
||||||
out.writeInt(policy.policy)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,11 @@ package com.topjohnwu.magisk.model.entity
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Ignore
|
import androidx.room.Ignore
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.ALLOW
|
||||||
import com.topjohnwu.magisk.extensions.now
|
import com.topjohnwu.magisk.extensions.now
|
||||||
import com.topjohnwu.magisk.extensions.timeFormatTime
|
import com.topjohnwu.magisk.extensions.timeFormatTime
|
||||||
import com.topjohnwu.magisk.extensions.toTime
|
import com.topjohnwu.magisk.extensions.toTime
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy.Companion.ALLOW
|
|
||||||
|
|
||||||
@Entity(tableName = "logs")
|
@Entity(tableName = "logs")
|
||||||
data class MagiskLog(
|
data class MagiskLog(
|
||||||
@ -23,11 +24,6 @@ data class MagiskLog(
|
|||||||
@Ignore val timeString = time.toTime(timeFormatTime)
|
@Ignore val timeString = time.toTime(timeFormatTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WrappedMagiskLog(
|
|
||||||
val time: Long,
|
|
||||||
val items: List<MagiskLog>
|
|
||||||
)
|
|
||||||
|
|
||||||
fun MagiskPolicy.toLog(
|
fun MagiskPolicy.toLog(
|
||||||
toUid: Int,
|
toUid: Int,
|
||||||
fromPid: Int,
|
fromPid: Int,
|
||||||
|
@ -2,13 +2,13 @@ package com.topjohnwu.magisk.model.entity.internal
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
import com.topjohnwu.magisk.extensions.cachedFile
|
import com.topjohnwu.magisk.extensions.cachedFile
|
||||||
import com.topjohnwu.magisk.extensions.get
|
import com.topjohnwu.magisk.extensions.get
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskJson
|
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||||
import com.topjohnwu.magisk.model.entity.ManagerJson
|
import com.topjohnwu.magisk.core.model.ManagerJson
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
|
||||||
import kotlinx.android.parcel.IgnoredOnParcel
|
import kotlinx.android.parcel.IgnoredOnParcel
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -103,4 +103,4 @@ sealed class DownloadSubject : Parcelable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.recycler
|
package com.topjohnwu.magisk.model.entity.recycler
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
|
|
||||||
sealed class HomeItem : ComparableRvItem<HomeItem>() {
|
sealed class HomeItem : ComparableRvItem<HomeItem>() {
|
||||||
|
@ -7,9 +7,9 @@ import androidx.databinding.ViewDataBinding
|
|||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Module
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.model.entity.module.Module
|
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
|
||||||
import com.topjohnwu.magisk.ui.module.ModuleViewModel
|
import com.topjohnwu.magisk.ui.module.ModuleViewModel
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ package com.topjohnwu.magisk.model.entity.recycler
|
|||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.model.MagiskPolicy
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.extensions.toggle
|
import com.topjohnwu.magisk.extensions.toggle
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
|
||||||
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
|
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
|
||||||
import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel
|
import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
|
@ -2,7 +2,7 @@ package com.topjohnwu.magisk.model.events
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
|
|
||||||
interface ContextExecutor {
|
interface ContextExecutor {
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ interface ContextExecutor {
|
|||||||
|
|
||||||
interface ActivityExecutor {
|
interface ActivityExecutor {
|
||||||
|
|
||||||
operator fun invoke(activity: BaseActivity<*, *>)
|
operator fun invoke(activity: BaseActivity)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@ package com.topjohnwu.magisk.model.events
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.intent
|
import com.topjohnwu.magisk.core.intent
|
||||||
import com.topjohnwu.magisk.legacy.flash.FlashActivity
|
import com.topjohnwu.magisk.legacy.flash.FlashActivity
|
||||||
|
|
||||||
class InstallExternalModuleEvent : ViewEvent(), ActivityExecutor {
|
class InstallExternalModuleEvent : ViewEvent(), ActivityExecutor {
|
||||||
|
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
activity.withExternalRW {
|
activity.withExternalRW {
|
||||||
onSuccess {
|
onSuccess {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.model.events
|
package com.topjohnwu.magisk.model.events
|
||||||
|
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
import com.topjohnwu.magisk.core.model.MagiskPolicy
|
||||||
import com.topjohnwu.magisk.utils.RxBus
|
import com.topjohnwu.magisk.utils.RxBus
|
||||||
|
|
||||||
sealed class PolicyUpdateEvent(val item: MagiskPolicy) : RxBus.Event {
|
sealed class PolicyUpdateEvent(val item: MagiskPolicy) : RxBus.Event {
|
||||||
|
@ -3,8 +3,9 @@ package com.topjohnwu.magisk.model.events
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.extensions.snackbar
|
import com.topjohnwu.magisk.extensions.snackbar
|
||||||
|
import com.topjohnwu.magisk.ui.base.BaseUIActivity
|
||||||
|
|
||||||
class SnackbarEvent private constructor(
|
class SnackbarEvent private constructor(
|
||||||
@StringRes private val messageRes: Int,
|
@StringRes private val messageRes: Int,
|
||||||
@ -27,8 +28,8 @@ class SnackbarEvent private constructor(
|
|||||||
|
|
||||||
fun message(context: Context): String = messageString ?: context.getString(messageRes)
|
fun message(context: Context): String = messageString ?: context.getString(messageRes)
|
||||||
|
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
if (activity is BaseActivity<*, *>) {
|
if (activity is BaseUIActivity<*, *>) {
|
||||||
activity.snackbar(activity.snackbarView, message(activity), length, f)
|
activity.snackbar(activity.snackbarView, message(activity), length, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,16 @@ package com.topjohnwu.magisk.model.events
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||||
import com.topjohnwu.magisk.extensions.DynamicClassLoader
|
import com.topjohnwu.magisk.extensions.DynamicClassLoader
|
||||||
import com.topjohnwu.magisk.extensions.subscribeK
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.extensions.writeTo
|
import com.topjohnwu.magisk.extensions.writeTo
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
|
||||||
import com.topjohnwu.magisk.utils.RxBus
|
import com.topjohnwu.magisk.utils.RxBus
|
||||||
import com.topjohnwu.magisk.utils.SafetyNetHelper
|
import com.topjohnwu.magisk.core.utils.SafetyNetHelper
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -118,8 +118,8 @@ class UpdateSafetyNetEvent : ViewEvent(), ContextExecutor, KoinComponent, Safety
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewActionEvent(val action: BaseActivity<*, *>.() -> Unit) : ViewEvent(), ActivityExecutor {
|
class ViewActionEvent(val action: BaseActivity.() -> Unit) : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: BaseActivity<*, *>) = activity.run(action)
|
override fun invoke(activity: BaseActivity) = activity.run(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenChangelogEvent(val item: Repo) : ViewEvent(), ContextExecutor {
|
class OpenChangelogEvent(val item: Repo) : ViewEvent(), ContextExecutor {
|
||||||
@ -133,7 +133,7 @@ class PermissionEvent(
|
|||||||
val callback: PublishSubject<Boolean>
|
val callback: PublishSubject<Boolean>
|
||||||
) : ViewEvent(), ActivityExecutor {
|
) : ViewEvent(), ActivityExecutor {
|
||||||
|
|
||||||
override fun invoke(activity: BaseActivity<*, *>) =
|
override fun invoke(activity: BaseActivity) =
|
||||||
activity.withPermissions(*permissions.toTypedArray()) {
|
activity.withPermissions(*permissions.toTypedArray()) {
|
||||||
onSuccess {
|
onSuccess {
|
||||||
callback.onNext(true)
|
callback.onNext(true)
|
||||||
@ -146,25 +146,25 @@ class PermissionEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BackPressEvent : ViewEvent(), ActivityExecutor {
|
class BackPressEvent : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
activity.onBackPressed()
|
activity.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DieEvent : ViewEvent(), ActivityExecutor {
|
class DieEvent : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
activity.finish()
|
activity.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RecreateEvent : ViewEvent(), ActivityExecutor {
|
class RecreateEvent : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
activity.recreate()
|
activity.recreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RequestFileEvent : ViewEvent(), ActivityExecutor {
|
class RequestFileEvent : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
Intent(Intent.ACTION_GET_CONTENT)
|
Intent(Intent.ACTION_GET_CONTENT)
|
||||||
.setType("*/*")
|
.setType("*/*")
|
||||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.model.events.dialog
|
package com.topjohnwu.magisk.model.events.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||||
import com.topjohnwu.magisk.utils.BiometricHelper
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
|
|
||||||
class BiometricDialog(
|
class BiometricDialog(
|
||||||
builder: Builder.() -> Unit
|
builder: Builder.() -> Unit
|
||||||
@ -16,7 +16,7 @@ class BiometricDialog(
|
|||||||
builder(Builder())
|
builder(Builder())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
BiometricHelper.authenticate(
|
BiometricHelper.authenticate(
|
||||||
activity,
|
activity,
|
||||||
onError = listenerOnFailure,
|
onError = listenerOnFailure,
|
||||||
|
@ -2,9 +2,9 @@ package com.topjohnwu.magisk.model.events.dialog
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
@ -13,7 +13,7 @@ class DarkThemeDialog : DialogEvent(), ActivityExecutor {
|
|||||||
|
|
||||||
private var activity: WeakReference<Activity>? = null
|
private var activity: WeakReference<Activity>? = null
|
||||||
|
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
this.activity = WeakReference(activity)
|
this.activity = WeakReference(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,24 +1,14 @@
|
|||||||
package com.topjohnwu.magisk.model.events.dialog
|
package com.topjohnwu.magisk.model.events.dialog
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.net.toUri
|
|
||||||
import com.topjohnwu.magisk.Info
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.extensions.cachedFile
|
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||||
import com.topjohnwu.magisk.extensions.reboot
|
import com.topjohnwu.magisk.extensions.reboot
|
||||||
import com.topjohnwu.magisk.net.Networking
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.magisk.tasks.MagiskInstaller
|
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.superuser.Shell
|
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.get
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class EnvFixDialog : DialogEvent() {
|
class EnvFixDialog : DialogEvent() {
|
||||||
|
|
||||||
@ -48,19 +38,7 @@ class EnvFixDialog : DialogEvent() {
|
|||||||
|
|
||||||
private fun fixEnv(dialog: DialogInterface) {
|
private fun fixEnv(dialog: DialogInterface) {
|
||||||
object : MagiskInstaller(), KoinComponent {
|
object : MagiskInstaller(), KoinComponent {
|
||||||
override fun operations(): Boolean {
|
override fun operations() = fixEnv()
|
||||||
val context = get<Context>()
|
|
||||||
val zip: File = context.cachedFile("magisk.zip")
|
|
||||||
|
|
||||||
installDir = SuFile("/data/adb/magisk")
|
|
||||||
Shell.su("rm -rf /data/adb/magisk/*").exec()
|
|
||||||
|
|
||||||
if (!ShellUtils.checkSum("MD5", zip, Info.remote.magisk.md5))
|
|
||||||
Networking.get(Info.remote.magisk.link).execForFile(zip)
|
|
||||||
|
|
||||||
zipUri = zip.toUri()
|
|
||||||
return extractZip() && Shell.su("fix_env").exec().isSuccess
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResult(success: Boolean) {
|
override fun onResult(success: Boolean) {
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
@ -74,4 +52,4 @@ class EnvFixDialog : DialogEvent() {
|
|||||||
}.exec()
|
}.exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,16 @@ import android.Manifest
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
import com.topjohnwu.magisk.databinding.IncludeInstallOptionsBinding
|
import com.topjohnwu.magisk.databinding.IncludeInstallOptionsBinding
|
||||||
import com.topjohnwu.magisk.extensions.hasPermissions
|
import com.topjohnwu.magisk.extensions.hasPermissions
|
||||||
import com.topjohnwu.magisk.extensions.res
|
import com.topjohnwu.magisk.extensions.res
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService
|
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.events.OpenInappLinkEvent
|
import com.topjohnwu.magisk.model.events.OpenInappLinkEvent
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -128,4 +128,4 @@ class MagiskInstallDialog : DialogEvent() {
|
|||||||
.fastCmd("grep_prop ro.build.ab_update")
|
.fastCmd("grep_prop ro.build.ab_update")
|
||||||
.let { it.isNotEmpty() && it.toBoolean() }
|
.let { it.isNotEmpty() && it.toBoolean() }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.model.events.dialog
|
package com.topjohnwu.magisk.model.events.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
import com.topjohnwu.magisk.extensions.res
|
import com.topjohnwu.magisk.extensions.res
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService
|
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
@ -33,4 +33,4 @@ class ManagerInstallDialog : DialogEvent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.model.events.dialog
|
package com.topjohnwu.magisk.model.events.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
|
import com.topjohnwu.magisk.core.model.module.Repo
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.entity.module.Repo
|
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
|
||||||
class ModuleInstallDialog(private val item: Repo) : DialogEvent() {
|
class ModuleInstallDialog(private val item: Repo) : DialogEvent() {
|
||||||
@ -34,4 +34,4 @@ class ModuleInstallDialog(private val item: Repo) : DialogEvent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.model.events.dialog
|
package com.topjohnwu.magisk.model.events.dialog
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.model.download.DownloadService
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
|
|
||||||
@ -52,4 +52,4 @@ class UninstallDialog : DialogEvent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package com.topjohnwu.magisk.model.flash
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.os.postDelayed
|
import androidx.core.os.postDelayed
|
||||||
|
import com.topjohnwu.magisk.core.tasks.FlashZip
|
||||||
import com.topjohnwu.magisk.extensions.inject
|
import com.topjohnwu.magisk.extensions.inject
|
||||||
import com.topjohnwu.magisk.tasks.FlashZip
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
|
|
||||||
@ -58,4 +58,4 @@ sealed class Flashing(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.model.flash
|
package com.topjohnwu.magisk.model.flash
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.topjohnwu.magisk.tasks.MagiskInstaller
|
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
|
|
||||||
sealed class Patching(
|
sealed class Patching(
|
||||||
@ -28,8 +28,7 @@ sealed class Patching(
|
|||||||
logs: MutableList<String>,
|
logs: MutableList<String>,
|
||||||
resultListener: FlashResultListener
|
resultListener: FlashResultListener
|
||||||
) : Patching(file, console, logs, resultListener) {
|
) : Patching(file, console, logs, resultListener) {
|
||||||
override fun operations() =
|
override fun operations() = doPatchFile(uri)
|
||||||
extractZip() && handleFile(uri) && patchBoot() && storeBoot()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SecondSlot(
|
class SecondSlot(
|
||||||
@ -38,8 +37,7 @@ sealed class Patching(
|
|||||||
logs: MutableList<String>,
|
logs: MutableList<String>,
|
||||||
resultListener: FlashResultListener
|
resultListener: FlashResultListener
|
||||||
) : Patching(file, console, logs, resultListener) {
|
) : Patching(file, console, logs, resultListener) {
|
||||||
override fun operations() =
|
override fun operations() = secondSlot()
|
||||||
findSecondaryImage() && extractZip() && patchBoot() && flashBoot() && postOTA()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Direct(
|
class Direct(
|
||||||
@ -48,8 +46,7 @@ sealed class Patching(
|
|||||||
logs: MutableList<String>,
|
logs: MutableList<String>,
|
||||||
resultListener: FlashResultListener
|
resultListener: FlashResultListener
|
||||||
) : Patching(file, console, logs, resultListener) {
|
) : Patching(file, console, logs, resultListener) {
|
||||||
override fun operations() =
|
override fun operations() = direct()
|
||||||
findImage() && extractZip() && patchBoot() && flashBoot()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ import android.os.Bundle
|
|||||||
import androidx.annotation.AnimRes
|
import androidx.annotation.AnimRes
|
||||||
import androidx.annotation.AnimatorRes
|
import androidx.annotation.AnimatorRes
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||||
import com.topjohnwu.magisk.ui.compat.CompatActivity
|
import com.topjohnwu.magisk.ui.base.CompatActivity
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@ -23,7 +23,7 @@ class MagiskNavigationEvent(
|
|||||||
operator fun invoke(builder: Builder.() -> Unit) = Builder().apply(builder).build()
|
operator fun invoke(builder: Builder.() -> Unit) = Builder().apply(builder).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(activity: BaseActivity<*, *>) {
|
override fun invoke(activity: BaseActivity) {
|
||||||
if (activity !is CompatActivity<*, *>) return
|
if (activity !is CompatActivity<*, *>) return
|
||||||
activity.navigation?.navigateTo(this)
|
activity.navigation?.navigateTo(this)
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package com.topjohnwu.magisk.model.navigation
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.intent
|
import com.topjohnwu.magisk.core.intent
|
||||||
import com.topjohnwu.magisk.ui.MainActivity
|
import com.topjohnwu.magisk.ui.MainActivity
|
||||||
import com.topjohnwu.magisk.ui.hide.HideFragment
|
import com.topjohnwu.magisk.ui.hide.HideFragment
|
||||||
import com.topjohnwu.magisk.ui.home.HomeFragment
|
import com.topjohnwu.magisk.ui.home.HomeFragment
|
||||||
@ -82,7 +82,9 @@ object Navigation {
|
|||||||
|
|
||||||
fun start(launchIntent: Intent, context: Context) {
|
fun start(launchIntent: Intent, context: Context) {
|
||||||
context.intent<MainActivity>()
|
context.intent<MainActivity>()
|
||||||
.putExtra(Const.Key.OPEN_SECTION, launchIntent.getStringExtra(Const.Key.OPEN_SECTION))
|
.putExtra(
|
||||||
|
Const.Key.OPEN_SECTION, launchIntent.getStringExtra(
|
||||||
|
Const.Key.OPEN_SECTION))
|
||||||
.putExtra(
|
.putExtra(
|
||||||
Const.Key.OPEN_SETTINGS,
|
Const.Key.OPEN_SETTINGS,
|
||||||
launchIntent.action == ACTION_APPLICATION_PREFERENCES
|
launchIntent.action == ACTION_APPLICATION_PREFERENCES
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.model.zip
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.extensions.forEach
|
|
||||||
import com.topjohnwu.magisk.extensions.withStreams
|
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
|
||||||
import java.io.File
|
|
||||||
import java.util.zip.ZipInputStream
|
|
||||||
|
|
||||||
|
|
||||||
class Zip private constructor(private val values: Builder) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
operator fun invoke(builder: Builder.() -> Unit): Zip {
|
|
||||||
return Zip(Builder().apply(builder))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Builder {
|
|
||||||
lateinit var zip: File
|
|
||||||
lateinit var destination: File
|
|
||||||
var excludeDirs = true
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Path(val path: String, val pullFromDir: Boolean = true)
|
|
||||||
|
|
||||||
fun unzip(vararg paths: Pair<String, Boolean>) =
|
|
||||||
unzip(*paths.map { Path(it.first, it.second) }.toTypedArray())
|
|
||||||
|
|
||||||
@Suppress("RedundantLambdaArrow")
|
|
||||||
fun unzip(vararg paths: Path) {
|
|
||||||
ensureRequiredParams()
|
|
||||||
|
|
||||||
values.zip.zipStream().use {
|
|
||||||
it.forEach { e ->
|
|
||||||
val currentPath = paths.firstOrNull { e.name.startsWith(it.path) }
|
|
||||||
val isDirectory = values.excludeDirs && e.isDirectory
|
|
||||||
if (currentPath == null || isDirectory) {
|
|
||||||
// Ignore directories, only create files
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
|
|
||||||
val name = if (currentPath.pullFromDir) {
|
|
||||||
e.name.substring(e.name.lastIndexOf('/') + 1)
|
|
||||||
} else {
|
|
||||||
e.name
|
|
||||||
}
|
|
||||||
|
|
||||||
val out = File(values.destination, name)
|
|
||||||
.ensureExists()
|
|
||||||
.outputStream()
|
|
||||||
//.suOutputStream()
|
|
||||||
|
|
||||||
withStreams(it, out) { reader, writer ->
|
|
||||||
reader.copyTo(writer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ensureRequiredParams() {
|
|
||||||
if (!values.zip.exists()) {
|
|
||||||
throw RuntimeException("Zip file does not exist")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun File.ensureExists() =
|
|
||||||
if ((!parentFile.exists() && !parentFile.mkdirs()) || parentFile is SuFile) {
|
|
||||||
SuFile(parentFile, name).apply { parentFile.mkdirs() }
|
|
||||||
} else {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun File.zipStream() = ZipInputStream(inputStream())
|
|
||||||
|
|
||||||
}
|
|
@ -12,13 +12,13 @@ import androidx.core.view.updateLayoutParams
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.ncapdevi.fragnav.FragNavController
|
import com.ncapdevi.fragnav.FragNavController
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
||||||
import com.topjohnwu.magisk.extensions.startAnimations
|
import com.topjohnwu.magisk.extensions.startAnimations
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
import com.topjohnwu.magisk.model.navigation.Navigation
|
||||||
import com.topjohnwu.magisk.ui.compat.CompatActivity
|
import com.topjohnwu.magisk.ui.base.CompatActivity
|
||||||
import com.topjohnwu.magisk.ui.compat.CompatNavigationDelegate
|
import com.topjohnwu.magisk.ui.base.CompatNavigationDelegate
|
||||||
import com.topjohnwu.magisk.ui.home.HomeFragment
|
import com.topjohnwu.magisk.ui.home.HomeFragment
|
||||||
import com.topjohnwu.magisk.ui.module.ModuleFragment
|
import com.topjohnwu.magisk.ui.module.ModuleFragment
|
||||||
import com.topjohnwu.magisk.ui.superuser.SuperuserFragment
|
import com.topjohnwu.magisk.ui.superuser.SuperuserFragment
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.ui
|
package com.topjohnwu.magisk.ui
|
||||||
|
|
||||||
import com.topjohnwu.magisk.base.BaseViewModel
|
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||||
|
|
||||||
class MainViewModel : BaseViewModel()
|
class MainViewModel : BaseViewModel()
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.databinding.ViewDataBinding
|
||||||
|
import com.topjohnwu.magisk.BR
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
|
import com.topjohnwu.magisk.model.events.EventHandler
|
||||||
|
|
||||||
|
abstract class BaseUIActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
||||||
|
BaseActivity(), EventHandler {
|
||||||
|
|
||||||
|
protected lateinit var binding: Binding
|
||||||
|
protected abstract val layoutRes: Int
|
||||||
|
protected abstract val viewModel: ViewModel
|
||||||
|
protected open val themeRes: Int = R.style.MagiskTheme
|
||||||
|
|
||||||
|
open val snackbarView get() = binding.root
|
||||||
|
|
||||||
|
init {
|
||||||
|
val theme = Config.darkThemeExtended
|
||||||
|
AppCompatDelegate.setDefaultNightMode(theme)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTheme(themeRes)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
viewModel.viewEvents.observe(this, viewEventObserver)
|
||||||
|
|
||||||
|
binding = DataBindingUtil.setContentView<Binding>(this, layoutRes).apply {
|
||||||
|
setVariable(BR.viewModel, viewModel)
|
||||||
|
lifecycleOwner = this@BaseUIActivity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.base
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -11,10 +11,10 @@ import com.topjohnwu.magisk.BR
|
|||||||
import com.topjohnwu.magisk.model.events.EventHandler
|
import com.topjohnwu.magisk.model.events.EventHandler
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||||
|
|
||||||
abstract class BaseFragment<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
abstract class BaseUIFragment<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
||||||
Fragment(), EventHandler {
|
Fragment(), EventHandler {
|
||||||
|
|
||||||
protected val activity get() = requireActivity() as BaseActivity<*, *>
|
protected val activity get() = requireActivity() as BaseUIActivity<*, *>
|
||||||
protected lateinit var binding: Binding
|
protected lateinit var binding: Binding
|
||||||
protected abstract val layoutRes: Int
|
protected abstract val layoutRes: Int
|
||||||
protected abstract val viewModel: ViewModel
|
protected abstract val viewModel: ViewModel
|
||||||
@ -31,7 +31,7 @@ abstract class BaseFragment<ViewModel : BaseViewModel, Binding : ViewDataBinding
|
|||||||
): View? {
|
): View? {
|
||||||
binding = DataBindingUtil.inflate<Binding>(inflater, layoutRes, container, false).apply {
|
binding = DataBindingUtil.inflate<Binding>(inflater, layoutRes, container, false).apply {
|
||||||
setVariable(BR.viewModel, viewModel)
|
setVariable(BR.viewModel, viewModel)
|
||||||
lifecycleOwner = this@BaseFragment
|
lifecycleOwner = this@BaseUIFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.base
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
@ -8,7 +8,8 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.extensions.doOnSubscribeUi
|
import com.topjohnwu.magisk.extensions.doOnSubscribeUi
|
||||||
import com.topjohnwu.magisk.model.events.*
|
import com.topjohnwu.magisk.model.events.*
|
||||||
import com.topjohnwu.magisk.model.observer.Observer
|
import com.topjohnwu.magisk.model.observer.Observer
|
||||||
@ -79,7 +80,7 @@ abstract class BaseViewModel(
|
|||||||
super.onCleared()
|
super.onCleared()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withView(action: BaseActivity<*, *>.() -> Unit) {
|
fun withView(action: BaseActivity.() -> Unit) {
|
||||||
ViewActionEvent(action).publish()
|
ViewActionEvent(action).publish()
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.ui.compat
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -10,8 +10,6 @@ import androidx.core.content.getSystemService
|
|||||||
import androidx.databinding.OnRebindCallback
|
import androidx.databinding.OnRebindCallback
|
||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
|
||||||
import com.topjohnwu.magisk.base.BaseViewModel
|
|
||||||
import com.topjohnwu.magisk.extensions.snackbar
|
import com.topjohnwu.magisk.extensions.snackbar
|
||||||
import com.topjohnwu.magisk.extensions.startAnimations
|
import com.topjohnwu.magisk.extensions.startAnimations
|
||||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||||
@ -20,9 +18,10 @@ import com.topjohnwu.magisk.model.navigation.Navigator
|
|||||||
import com.topjohnwu.magisk.ui.theme.Theme
|
import com.topjohnwu.magisk.ui.theme.Theme
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
// TODO (diareuse): Merge into BaseUIActivity after all legacy UI is migrated
|
||||||
|
|
||||||
abstract class CompatActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
abstract class CompatActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
||||||
BaseActivity<ViewModel, Binding>(), CompatView<ViewModel>, Navigator {
|
BaseUIActivity<ViewModel, Binding>(), CompatView<ViewModel>, Navigator {
|
||||||
|
|
||||||
override val themeRes = Theme.selected.themeRes
|
override val themeRes = Theme.selected.themeRes
|
||||||
override val viewRoot: View get() = binding.root
|
override val viewRoot: View get() = binding.root
|
@ -1,11 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.ui.compat
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
|
||||||
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
import com.topjohnwu.magisk.model.events.ActivityExecutor
|
||||||
import com.topjohnwu.magisk.model.events.ContextExecutor
|
import com.topjohnwu.magisk.model.events.ContextExecutor
|
||||||
import com.topjohnwu.magisk.model.events.FragmentExecutor
|
import com.topjohnwu.magisk.model.events.FragmentExecutor
|
||||||
@ -26,7 +25,7 @@ class CompatDelegate internal constructor(
|
|||||||
view.viewModel.requestRefresh()
|
view.viewModel.requestRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEventExecute(event: ViewEvent, activity: BaseActivity<*, *>) {
|
fun onEventExecute(event: ViewEvent, activity: BaseUIActivity<*, *>) {
|
||||||
(event as? ContextExecutor)?.invoke(activity)
|
(event as? ContextExecutor)?.invoke(activity)
|
||||||
(event as? ActivityExecutor)?.invoke(activity)
|
(event as? ActivityExecutor)?.invoke(activity)
|
||||||
(event as? FragmentExecutor)?.let {
|
(event as? FragmentExecutor)?.let {
|
||||||
@ -37,7 +36,7 @@ class CompatDelegate internal constructor(
|
|||||||
fun onEventExecute(event: ViewEvent, fragment: Fragment) {
|
fun onEventExecute(event: ViewEvent, fragment: Fragment) {
|
||||||
(event as? ContextExecutor)?.invoke(fragment.requireContext())
|
(event as? ContextExecutor)?.invoke(fragment.requireContext())
|
||||||
(event as? FragmentExecutor)?.invoke(fragment)
|
(event as? FragmentExecutor)?.invoke(fragment)
|
||||||
(event as? ActivityExecutor)?.invoke(fragment.requireActivity() as BaseActivity<*, *>)
|
(event as? ActivityExecutor)?.invoke(fragment.requireActivity() as BaseUIActivity<*, *>)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureInsets() {
|
private fun ensureInsets() {
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.ui.compat
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -6,13 +6,13 @@ import android.view.ViewGroup
|
|||||||
import androidx.databinding.OnRebindCallback
|
import androidx.databinding.OnRebindCallback
|
||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseFragment
|
|
||||||
import com.topjohnwu.magisk.base.BaseViewModel
|
|
||||||
import com.topjohnwu.magisk.extensions.startAnimations
|
import com.topjohnwu.magisk.extensions.startAnimations
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||||
|
|
||||||
|
// TODO (diareuse): Merge into BaseUIFragment after all legacy UI is migrated
|
||||||
|
|
||||||
abstract class CompatFragment<ViewModel : BaseViewModel, Binding : ViewDataBinding>
|
abstract class CompatFragment<ViewModel : BaseViewModel, Binding : ViewDataBinding>
|
||||||
: BaseFragment<ViewModel, Binding>(), CompatView<ViewModel> {
|
: BaseUIFragment<ViewModel, Binding>(), CompatView<ViewModel> {
|
||||||
|
|
||||||
override val viewRoot: View get() = binding.root
|
override val viewRoot: View get() = binding.root
|
||||||
override val navigation by lazy { compatActivity.navigation }
|
override val navigation by lazy { compatActivity.navigation }
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.ui.compat
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.ui.compat
|
package com.topjohnwu.magisk.ui.base
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user