diff --git a/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt b/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt index 0c7a5098e..e327820e5 100644 --- a/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt @@ -70,6 +70,10 @@ abstract class BaseUIActivity : ensureInsets() } + fun setAccessibilityDelegate(delegate: View.AccessibilityDelegate?) { + viewRoot.rootView.accessibilityDelegate = delegate + } + override fun onResume() { super.onResume() viewModel.requestRefresh() @@ -79,7 +83,7 @@ abstract class BaseUIActivity : return currentFragment?.onKeyEvent(event) == true || super.dispatchKeyEvent(event) } - override fun onEventDispatched(event: ViewEvent) = when(event) { + override fun onEventDispatched(event: ViewEvent) = when (event) { is ContextExecutor -> event(this) is ActivityExecutor -> event(this) else -> Unit diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Config.kt b/app/src/main/java/com/topjohnwu/magisk/core/Config.kt index c7f5233fc..867497820 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Config.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Config.kt @@ -50,6 +50,7 @@ object Config : PreferenceModel, DBConfig { const val SU_AUTO_RESPONSE = "su_auto_response" const val SU_NOTIFICATION = "su_notification" const val SU_REAUTH = "su_reauth" + const val SU_TAPJACK = "su_tapjack" const val CHECK_UPDATES = "check_update" const val UPDATE_CHANNEL = "update_channel" const val CUSTOM_CHANNEL = "custom_channel" @@ -134,6 +135,7 @@ object Config : PreferenceModel, DBConfig { var darkTheme by preference(Key.DARK_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) var themeOrdinal by preference(Key.THEME_ORDINAL, Theme.Piplup.ordinal) var suReAuth by preference(Key.SU_REAUTH, false) + var suTapjack by preference(Key.SU_TAPJACK, true) var checkUpdate by preference(Key.CHECK_UPDATES, true) var doh by preference(Key.DOH, false) var magiskHide by preference(Key.MAGISKHIDE, true) diff --git a/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt b/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt index 54b0d5215..b72a1c6ad 100644 --- a/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt +++ b/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt @@ -4,6 +4,7 @@ import android.app.Activity import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent +import android.view.View import android.widget.Toast import androidx.navigation.NavDirections import com.topjohnwu.magisk.MainDirections @@ -58,9 +59,11 @@ class DieEvent : ViewEvent(), ActivityExecutor { } } -class ShowUIEvent : ViewEvent(), ActivityExecutor { +class ShowUIEvent(private val delegate: View.AccessibilityDelegate?) + : ViewEvent(), ActivityExecutor { override fun invoke(activity: BaseUIActivity<*, *>) { activity.setContentView() + activity.setAccessibilityDelegate(delegate) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt index 98bb424ad..70ccff441 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt @@ -195,6 +195,13 @@ object SystemlessHosts : BaseSettingsItem.Blank() { override val description = R.string.settings_hosts_summary.asTransitive() } +object Tapjack : BaseSettingsItem.Toggle() { + override val title = R.string.settings_su_tapjack_title.asTransitive() + override var description = R.string.settings_su_tapjack_summary.asTransitive() + override var value = Config.suTapjack + set(value) = setV(value, field, { field = it }) { Config.suTapjack = it } +} + object Biometrics : BaseSettingsItem.Toggle() { override val title = R.string.settings_su_biometric_title.asTransitive() override var value = Config.suBiometric diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt index afcd7533a..c9ab17bcd 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt @@ -79,7 +79,7 @@ class SettingsViewModel( if (Utils.showSuperUser()) { list.addAll(listOf( Superuser, - Biometrics, AccessMode, MultiuserMode, MountNamespaceMode, + Tapjack, Biometrics, AccessMode, MultiuserMode, MountNamespaceMode, AutomaticResponse, RequestTimeout, SUNotification )) if (Build.VERSION.SDK_INT < 23) { diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt index d5f49cb69..ed0a5d7f8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt @@ -28,8 +28,8 @@ open class SuRequestActivity : BaseUIActivity + // Filter obscured touches by consuming them. + if (event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0 + || event.flags and MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0) { + if (event.action == MotionEvent.ACTION_UP) { + Utils.toast(R.string.touch_filtered_warning, Toast.LENGTH_SHORT) + } + return@OnTouchListener Config.suTapjack + } + false + } + private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) } val adapter = BindingListViewAdapter(1).apply { itemBinding = ItemBinding.of { binding, _, item -> @@ -104,7 +127,7 @@ class SuRequestViewModel( timer = SuTimer(millis, 1000).apply { start() } // Actually show the UI - ShowUIEvent().publish() + ShowUIEvent(if (Config.suTapjack) EmptyAccessibilityDelegate else null).publish() } private fun respond(action: Int) { @@ -141,4 +164,18 @@ class SuRequestViewModel( } } + + // Invisible for accessibility services + object EmptyAccessibilityDelegate : View.AccessibilityDelegate() { + override fun sendAccessibilityEvent(host: View?, eventType: Int) {} + override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?) = true + override fun sendAccessibilityEventUnchecked(host: View?, event: AccessibilityEvent?) {} + override fun dispatchPopulateAccessibilityEvent(host: View?, event: AccessibilityEvent?) = true + override fun onPopulateAccessibilityEvent(host: View?, event: AccessibilityEvent?) {} + override fun onInitializeAccessibilityEvent(host: View?, event: AccessibilityEvent?) {} + override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {} + override fun addExtraDataToAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo, extraDataKey: String, arguments: Bundle?) {} + override fun onRequestSendAccessibilityEvent(host: ViewGroup?, child: View?, event: AccessibilityEvent?): Boolean = false + override fun getAccessibilityNodeProvider(host: View?): AccessibilityNodeProvider? = null + } } diff --git a/app/src/main/res/layout/activity_request.xml b/app/src/main/res/layout/activity_request.xml index c49ee363b..6183c2298 100644 --- a/app/src/main/res/layout/activity_request.xml +++ b/app/src/main/res/layout/activity_request.xml @@ -138,6 +138,7 @@