Only allow hide/restore app if connected
This commit is contained in:
parent
d010cb7e42
commit
0b5fd3ee76
@ -1,7 +1,11 @@
|
|||||||
package com.topjohnwu.magisk
|
package com.topjohnwu.magisk
|
||||||
|
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.topjohnwu.magisk.extensions.get
|
||||||
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.model.entity.UpdateInfo
|
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.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
|
|
||||||
@ -16,13 +20,27 @@ object Info {
|
|||||||
var keepEnc = false
|
var keepEnc = false
|
||||||
var recovery = false
|
var recovery = false
|
||||||
|
|
||||||
|
val isConnected by lazy {
|
||||||
|
KObservableField(false).also { field ->
|
||||||
|
ReactiveNetwork.observeNetworkConnectivity(get())
|
||||||
|
.subscribeK {
|
||||||
|
field.value = it.available()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadState() = runCatching {
|
private fun loadState() = runCatching {
|
||||||
val str = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0]
|
val str = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0]
|
||||||
val code = ShellUtils.fastCmd("magisk -V").toInt()
|
val code = ShellUtils.fastCmd("magisk -V").toInt()
|
||||||
val hide = Shell.su("magiskhide --status").exec().isSuccess
|
val hide = Shell.su("magiskhide --status").exec().isSuccess
|
||||||
var mode = Int.MAX_VALUE
|
var mode = -1
|
||||||
if (code >= Const.Version.CONNECT_MODE)
|
if (code >= Const.Version.CONNECT_MODE) {
|
||||||
mode = Shell.su("magisk --connect-mode").exec().code
|
mode = Shell.su("magisk --connect-mode").exec().code
|
||||||
|
if (mode == 0) {
|
||||||
|
// Manually trigger broadcast test
|
||||||
|
Shell.su("magisk --broadcast-test").exec()
|
||||||
|
}
|
||||||
|
}
|
||||||
Env(code, str, hide, mode)
|
Env(code, str, hide, mode)
|
||||||
}.getOrElse { Env() }
|
}.getOrElse { Env() }
|
||||||
|
|
||||||
@ -30,7 +48,7 @@ object Info {
|
|||||||
val magiskVersionCode: Int = -1,
|
val magiskVersionCode: Int = -1,
|
||||||
val magiskVersionString: String = "",
|
val magiskVersionString: String = "",
|
||||||
hide: Boolean = false,
|
hide: Boolean = false,
|
||||||
var connectionMode: Int = Int.MAX_VALUE
|
var connectionMode: Int = -1
|
||||||
) {
|
) {
|
||||||
val magiskHide get() = Config.magiskHide
|
val magiskHide get() = Config.magiskHide
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.base.viewmodel
|
package com.topjohnwu.magisk.base.viewmodel
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
import com.topjohnwu.magisk.Info.isConnected as gIsConnected
|
||||||
import com.topjohnwu.magisk.extensions.doOnSubscribeUi
|
import com.topjohnwu.magisk.extensions.doOnSubscribeUi
|
||||||
import com.topjohnwu.magisk.extensions.get
|
|
||||||
import com.topjohnwu.magisk.extensions.subscribeK
|
|
||||||
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.ViewActionEvent
|
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
||||||
@ -17,12 +15,10 @@ abstract class BaseViewModel(
|
|||||||
initialState: State = State.LOADING
|
initialState: State = State.LOADING
|
||||||
) : LoadingViewModel(initialState) {
|
) : LoadingViewModel(initialState) {
|
||||||
|
|
||||||
val isConnected = KObservableField(false)
|
val isConnected = object : KObservableField<Boolean>(gIsConnected.value, gIsConnected) {
|
||||||
|
override fun get(): Boolean {
|
||||||
init {
|
return gIsConnected.value
|
||||||
ReactiveNetwork.observeNetworkConnectivity(get())
|
}
|
||||||
.subscribeK { isConnected.value = it.available() }
|
|
||||||
.add()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withView(action: Activity.() -> Unit) {
|
fun withView(action: Activity.() -> Unit) {
|
||||||
|
@ -24,7 +24,6 @@ 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.observer.Observer
|
import com.topjohnwu.magisk.model.observer.Observer
|
||||||
import com.topjohnwu.magisk.net.Networking
|
|
||||||
import com.topjohnwu.magisk.utils.*
|
import com.topjohnwu.magisk.utils.*
|
||||||
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
|
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -54,6 +53,7 @@ class SettingsFragment : BasePreferenceFragment() {
|
|||||||
preferenceManager.setStorageDeviceProtected()
|
preferenceManager.setStorageDeviceProtected()
|
||||||
setPreferencesFromResource(R.xml.app_settings, rootKey)
|
setPreferencesFromResource(R.xml.app_settings, rootKey)
|
||||||
|
|
||||||
|
// Get preferences
|
||||||
updateChannel = findPreference(Config.Key.UPDATE_CHANNEL)!!
|
updateChannel = findPreference(Config.Key.UPDATE_CHANNEL)!!
|
||||||
rootConfig = findPreference(Config.Key.ROOT_ACCESS)!!
|
rootConfig = findPreference(Config.Key.ROOT_ACCESS)!!
|
||||||
autoRes = findPreference(Config.Key.SU_AUTO_RESPONSE)!!
|
autoRes = findPreference(Config.Key.SU_AUTO_RESPONSE)!!
|
||||||
@ -67,19 +67,68 @@ class SettingsFragment : BasePreferenceFragment() {
|
|||||||
val magiskCategory = findPreference<PreferenceCategory>("magisk")!!
|
val magiskCategory = findPreference<PreferenceCategory>("magisk")!!
|
||||||
val suCategory = findPreference<PreferenceCategory>("superuser")!!
|
val suCategory = findPreference<PreferenceCategory>("superuser")!!
|
||||||
val hideManager = findPreference<Preference>("hide")!!
|
val hideManager = findPreference<Preference>("hide")!!
|
||||||
hideManager.setOnPreferenceClickListener {
|
val restoreManager = findPreference<Preference>("restore")!!
|
||||||
showManagerNameDialog {
|
|
||||||
PatchAPK.hideManager(requireContext(), it)
|
// Remove/Disable entries
|
||||||
}
|
|
||||||
true
|
// Only show canary channels if user is already on canary channel
|
||||||
|
// or the user have already chosen canary channel
|
||||||
|
if (!Utils.isCanary && Config.updateChannel < Config.Value.CANARY_CHANNEL) {
|
||||||
|
// Remove the last 2 entries
|
||||||
|
val entries = updateChannel.entries
|
||||||
|
updateChannel.entries = entries.copyOf(entries.size - 2)
|
||||||
}
|
}
|
||||||
val restoreManager = findPreference<Preference>("restore")
|
|
||||||
restoreManager?.setOnPreferenceClickListener {
|
// Remove dangerous settings in secondary user
|
||||||
DownloadService(requireContext()) {
|
if (Const.USER_ID > 0) {
|
||||||
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
suCategory.removePreference(multiuserConfig)
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove re-authentication option on Android O, it will not work
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
suCategory.removePreference(reauth)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable fingerprint option if not possible
|
||||||
|
if (!FingerprintHelper.canUseFingerprint()) {
|
||||||
|
fingerprint.isEnabled = false
|
||||||
|
fingerprint.isChecked = false
|
||||||
|
fingerprint.setSummary(R.string.disable_fingerprint)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Const.USER_ID == 0 && Info.isConnected.value && Shell.rootAccess()) {
|
||||||
|
if (activity.packageName == BuildConfig.APPLICATION_ID) {
|
||||||
|
generalCatagory.removePreference(restoreManager)
|
||||||
|
hideManager.setOnPreferenceClickListener {
|
||||||
|
showManagerNameDialog {
|
||||||
|
PatchAPK.hideManager(requireContext(), it)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
generalCatagory.removePreference(hideManager)
|
||||||
|
restoreManager.setOnPreferenceClickListener {
|
||||||
|
DownloadService(requireContext()) {
|
||||||
|
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Remove if not primary user, no connection, or no root
|
||||||
|
generalCatagory.removePreference(restoreManager)
|
||||||
|
generalCatagory.removePreference(hideManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Utils.showSuperUser()) {
|
||||||
|
preferenceScreen.removePreference(suCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Shell.rootAccess()) {
|
||||||
|
preferenceScreen.removePreference(magiskCategory)
|
||||||
|
generalCatagory.removePreference(hideManager)
|
||||||
|
}
|
||||||
|
|
||||||
findPreference<Preference>("clear")?.setOnPreferenceClickListener {
|
findPreference<Preference>("clear")?.setOnPreferenceClickListener {
|
||||||
Completable.fromAction { repoDB.clear() }.subscribeK {
|
Completable.fromAction { repoDB.clear() }.subscribeK {
|
||||||
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT)
|
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT)
|
||||||
@ -123,58 +172,7 @@ class SettingsFragment : BasePreferenceFragment() {
|
|||||||
|
|
||||||
setLocalePreference(findPreference(Config.Key.LOCALE)!!)
|
setLocalePreference(findPreference(Config.Key.LOCALE)!!)
|
||||||
|
|
||||||
/* We only show canary channels if user is already on canary channel
|
|
||||||
* or the user have already chosen canary channel */
|
|
||||||
if (!Utils.isCanary && Config.updateChannel < Config.Value.CANARY_CHANNEL) {
|
|
||||||
// Remove the last 2 entries
|
|
||||||
val entries = updateChannel.entries
|
|
||||||
updateChannel.entries = entries.copyOf(entries.size - 2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setSummary()
|
setSummary()
|
||||||
|
|
||||||
// Disable dangerous settings in secondary user
|
|
||||||
if (Const.USER_ID > 0) {
|
|
||||||
suCategory.removePreference(multiuserConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable re-authentication option on Android O, it will not work
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
reauth.isEnabled = false
|
|
||||||
reauth.isChecked = false
|
|
||||||
reauth.setSummary(R.string.android_o_not_support)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable fingerprint option if not possible
|
|
||||||
if (!FingerprintHelper.canUseFingerprint()) {
|
|
||||||
fingerprint.isEnabled = false
|
|
||||||
fingerprint.isChecked = false
|
|
||||||
fingerprint.setSummary(R.string.disable_fingerprint)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Shell.rootAccess() && Const.USER_ID == 0) {
|
|
||||||
if (activity.packageName == BuildConfig.APPLICATION_ID) {
|
|
||||||
generalCatagory.removePreference(restoreManager)
|
|
||||||
} else {
|
|
||||||
if (!Networking.checkNetworkStatus(requireContext())) {
|
|
||||||
generalCatagory.removePreference(restoreManager)
|
|
||||||
}
|
|
||||||
generalCatagory.removePreference(hideManager)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
generalCatagory.removePreference(restoreManager)
|
|
||||||
generalCatagory.removePreference(hideManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Utils.showSuperUser()) {
|
|
||||||
preferenceScreen.removePreference(suCategory)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Shell.rootAccess()) {
|
|
||||||
preferenceScreen.removePreference(magiskCategory)
|
|
||||||
generalCatagory.removePreference(hideManager)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) {
|
||||||
|
@ -9,15 +9,11 @@ import java.io.Serializable
|
|||||||
* You can define if wrapped type is Nullable or not.
|
* You can define if wrapped type is Nullable or not.
|
||||||
* You can use kotlin get/set syntax for value
|
* You can use kotlin get/set syntax for value
|
||||||
*/
|
*/
|
||||||
class KObservableField<T> : ObservableField<T>, Serializable {
|
open class KObservableField<T> : ObservableField<T>, Serializable {
|
||||||
|
|
||||||
var value: T
|
var value: T
|
||||||
set(value) {
|
get() = get()
|
||||||
if (field != value) {
|
set(value) { set(value) }
|
||||||
field = value
|
|
||||||
notifyChange()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(init: T) {
|
constructor(init: T) {
|
||||||
value = init
|
value = init
|
||||||
@ -27,23 +23,8 @@ class KObservableField<T> : ObservableField<T>, Serializable {
|
|||||||
value = init
|
value = init
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated(
|
@Suppress("UNCHECKED_CAST")
|
||||||
message = "Needed for data binding, use KObservableField.value syntax from code",
|
|
||||||
replaceWith = ReplaceWith("value")
|
|
||||||
)
|
|
||||||
override fun get(): T {
|
override fun get(): T {
|
||||||
return value
|
return super.get() as T
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Deprecated(
|
|
||||||
message = "Needed for data binding, use KObservableField.value = ... syntax from code",
|
|
||||||
replaceWith = ReplaceWith("value = newValue")
|
|
||||||
)
|
|
||||||
override fun set(newValue: T) {
|
|
||||||
value = newValue
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "KObservableField(value=$value)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -39,11 +39,6 @@ class RootInit : Shell.Initializer() {
|
|||||||
Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean()
|
Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean()
|
||||||
Info.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean()
|
Info.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean()
|
||||||
|
|
||||||
if (Info.env.connectionMode == 0) {
|
|
||||||
// Manually trigger broadcast test
|
|
||||||
Shell.su("magisk --broadcast-test").exec()
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user