Only allow hide/restore app if connected

This commit is contained in:
topjohnwu 2019-10-23 05:43:01 -04:00
parent d010cb7e42
commit 0b5fd3ee76
5 changed files with 93 additions and 105 deletions

View File

@ -1,7 +1,11 @@
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.utils.CachedValue
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
@ -16,13 +20,27 @@ object Info {
var keepEnc = false
var recovery = false
val isConnected by lazy {
KObservableField(false).also { field ->
ReactiveNetwork.observeNetworkConnectivity(get())
.subscribeK {
field.value = it.available()
}
}
}
private fun loadState() = runCatching {
val str = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0]
val code = ShellUtils.fastCmd("magisk -V").toInt()
val hide = Shell.su("magiskhide --status").exec().isSuccess
var mode = Int.MAX_VALUE
if (code >= Const.Version.CONNECT_MODE)
var mode = -1
if (code >= Const.Version.CONNECT_MODE) {
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)
}.getOrElse { Env() }
@ -30,7 +48,7 @@ object Info {
val magiskVersionCode: Int = -1,
val magiskVersionString: String = "",
hide: Boolean = false,
var connectionMode: Int = Int.MAX_VALUE
var connectionMode: Int = -1
) {
val magiskHide get() = Config.magiskHide

View File

@ -1,10 +1,8 @@
package com.topjohnwu.magisk.base.viewmodel
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.get
import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.model.events.BackPressEvent
import com.topjohnwu.magisk.model.events.PermissionEvent
import com.topjohnwu.magisk.model.events.ViewActionEvent
@ -17,12 +15,10 @@ abstract class BaseViewModel(
initialState: State = State.LOADING
) : LoadingViewModel(initialState) {
val isConnected = KObservableField(false)
init {
ReactiveNetwork.observeNetworkConnectivity(get())
.subscribeK { isConnected.value = it.available() }
.add()
val isConnected = object : KObservableField<Boolean>(gIsConnected.value, gIsConnected) {
override fun get(): Boolean {
return gIsConnected.value
}
}
fun withView(action: Activity.() -> Unit) {

View File

@ -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.DownloadSubject
import com.topjohnwu.magisk.model.observer.Observer
import com.topjohnwu.magisk.net.Networking
import com.topjohnwu.magisk.utils.*
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
import com.topjohnwu.superuser.Shell
@ -54,6 +53,7 @@ class SettingsFragment : BasePreferenceFragment() {
preferenceManager.setStorageDeviceProtected()
setPreferencesFromResource(R.xml.app_settings, rootKey)
// Get preferences
updateChannel = findPreference(Config.Key.UPDATE_CHANNEL)!!
rootConfig = findPreference(Config.Key.ROOT_ACCESS)!!
autoRes = findPreference(Config.Key.SU_AUTO_RESPONSE)!!
@ -67,19 +67,68 @@ class SettingsFragment : BasePreferenceFragment() {
val magiskCategory = findPreference<PreferenceCategory>("magisk")!!
val suCategory = findPreference<PreferenceCategory>("superuser")!!
val hideManager = findPreference<Preference>("hide")!!
hideManager.setOnPreferenceClickListener {
showManagerNameDialog {
PatchAPK.hideManager(requireContext(), it)
}
true
val restoreManager = findPreference<Preference>("restore")!!
// Remove/Disable entries
// 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 {
DownloadService(requireContext()) {
subject = DownloadSubject.Manager(Configuration.APK.Restore)
}
true
// Remove dangerous settings in secondary user
if (Const.USER_ID > 0) {
suCategory.removePreference(multiuserConfig)
}
// 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 {
Completable.fromAction { repoDB.clear() }.subscribeK {
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT)
@ -123,58 +172,7 @@ class SettingsFragment : BasePreferenceFragment() {
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()
// 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) {

View File

@ -9,15 +9,11 @@ import java.io.Serializable
* You can define if wrapped type is Nullable or not.
* 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
set(value) {
if (field != value) {
field = value
notifyChange()
}
}
get() = get()
set(value) { set(value) }
constructor(init: T) {
value = init
@ -27,23 +23,8 @@ class KObservableField<T> : ObservableField<T>, Serializable {
value = init
}
@Deprecated(
message = "Needed for data binding, use KObservableField.value syntax from code",
replaceWith = ReplaceWith("value")
)
@Suppress("UNCHECKED_CAST")
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)"
}
}
}

View File

@ -39,11 +39,6 @@ class RootInit : Shell.Initializer() {
Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").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
}
}