From 0b5fd3ee761037d071d239b2f098c2ced35810fd Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 23 Oct 2019 05:43:01 -0400 Subject: [PATCH] Only allow hide/restore app if connected --- .../main/java/com/topjohnwu/magisk/Info.kt | 24 +++- .../magisk/base/viewmodel/BaseViewModel.kt | 14 +- .../magisk/ui/settings/SettingsFragment.kt | 124 +++++++++--------- .../magisk/utils/KObservableField.kt | 31 +---- .../com/topjohnwu/magisk/utils/RootInit.kt | 5 - 5 files changed, 93 insertions(+), 105 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/Info.kt b/app/src/main/java/com/topjohnwu/magisk/Info.kt index 54de52dd6..33b8715d4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/Info.kt +++ b/app/src/main/java/com/topjohnwu/magisk/Info.kt @@ -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 diff --git a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt index a9acc6ebb..ef9082aaa 100644 --- a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt @@ -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(gIsConnected.value, gIsConnected) { + override fun get(): Boolean { + return gIsConnected.value + } } fun withView(action: Activity.() -> Unit) { diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt index f191defb3..10c1059cf 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt @@ -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("magisk")!! val suCategory = findPreference("superuser")!! val hideManager = findPreference("hide")!! - hideManager.setOnPreferenceClickListener { - showManagerNameDialog { - PatchAPK.hideManager(requireContext(), it) - } - true + val restoreManager = findPreference("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("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("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) { diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/KObservableField.kt b/app/src/main/java/com/topjohnwu/magisk/utils/KObservableField.kt index 7ecf125f4..cda0e5eb0 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/KObservableField.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/KObservableField.kt @@ -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 : ObservableField, Serializable { +open class KObservableField : ObservableField, 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 : ObservableField, 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)" - } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt b/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt index c9b13c70c..c7c01a1d1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt @@ -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 } }