From c60b8b87c285f01c052226401232a3c622006635 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Mon, 12 Sep 2022 20:58:12 -0400 Subject: [PATCH 01/10] Add option to use AccessibilityService to create overlay --- app/src/main/AndroidManifest.xml | 10 ++++ .../redmoon/CommandAnimatorListener.kt | 7 ++- .../main/java/com/jmstudios/redmoon/Config.kt | 2 + .../java/com/jmstudios/redmoon/EventBus.kt | 2 + .../redmoon/fragment/SettingsFragment.kt | 25 ++++++++ .../service/AccessibilityFilterService.kt | 57 +++++++++++++++++++ .../redmoon/service/FilterService.kt | 24 ++++---- app/src/main/res/values/donottranslate.xml | 1 + app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/settings.xml | 9 +++ 10 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c75f32be..5dab121b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -153,5 +153,15 @@ + + + + + + diff --git a/app/src/main/java/com/jmstudios/redmoon/CommandAnimatorListener.kt b/app/src/main/java/com/jmstudios/redmoon/CommandAnimatorListener.kt index ae71a200..6be20710 100644 --- a/app/src/main/java/com/jmstudios/redmoon/CommandAnimatorListener.kt +++ b/app/src/main/java/com/jmstudios/redmoon/CommandAnimatorListener.kt @@ -25,11 +25,14 @@ package com.jmstudios.redmoon import android.animation.Animator +import android.app.Service +import com.jmstudios.redmoon.service.AccessibilityFilterService import com.jmstudios.redmoon.service.FilterService class CommandAnimatorListener( - private val cmd: Command, - private val svc: FilterService) + private val cmd: Command, + private val svc: FilterService, +) : Animator.AnimatorListener { override fun onAnimationStart (a: Animator?) = cmd.onAnimationStart (svc) diff --git a/app/src/main/java/com/jmstudios/redmoon/Config.kt b/app/src/main/java/com/jmstudios/redmoon/Config.kt index 54cc57c0..57c3e682 100644 --- a/app/src/main/java/com/jmstudios/redmoon/Config.kt +++ b/app/src/main/java/com/jmstudios/redmoon/Config.kt @@ -203,6 +203,8 @@ object Config : Preferences(appContext) { } var useRoot by BooleanPreference(R.string.pref_key_use_root, false) + + var useAccessibilityService by BooleanPreference(R.string.pref_key_use_accessibility_service, false) //endregion //region application diff --git a/app/src/main/java/com/jmstudios/redmoon/EventBus.kt b/app/src/main/java/com/jmstudios/redmoon/EventBus.kt index 2f2b3103..44701b7c 100644 --- a/app/src/main/java/com/jmstudios/redmoon/EventBus.kt +++ b/app/src/main/java/com/jmstudios/redmoon/EventBus.kt @@ -38,4 +38,6 @@ class overlayPermissionDenied : Event class locationAccessDenied : Event class changeBrightnessDenied : Event +class accessibilityServiceCommand(val command: Command) : Event + data class locationService(val isSearching: Boolean, val isRunning: Boolean = true) : Event diff --git a/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt b/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt index 58e6abf4..599a6a3f 100644 --- a/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt @@ -5,7 +5,9 @@ */ package com.jmstudios.redmoon.fragment +import android.content.Intent import android.os.Bundle +import android.provider.Settings import android.view.ViewGroup import android.widget.TextView import android.widget.Toast @@ -57,6 +59,9 @@ class SettingsFragment : PreferenceFragmentCompat() { private val rootPref: SwitchPreference get() = pref(R.string.pref_key_use_root) as SwitchPreference + private val accessibilityServicePref: SwitchPreference + get() = pref(R.string.pref_key_use_accessibility_service) as SwitchPreference + private var mSnackbar: Snackbar? = null override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { @@ -121,6 +126,26 @@ class SettingsFragment : PreferenceFragmentCompat() { return@setOnPreferenceChangeListener true } + accessibilityServicePref.setOnPreferenceChangeListener { _, newValue -> + // Make sure root is available before enabling + if (newValue as Boolean) { + val prefString = Settings.Secure.getString(context?.contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) + Log.i("FOO 20 FOO 10 ${context?.contentResolver } $prefString") + if(prefString == null || !prefString.contains("com.jmstudios.redmoon.service.AccessibilityFilterService")) { + startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)); + return@setOnPreferenceChangeListener false + } + } + if (filterIsOn) { + // It would be better to toggle back on again using the new mode but it's more work + // to add that, since the filter service needs to restart, so we need to wait until + // the fade-out finishes to start again. Or maybe better, the filter service could + // listen for this setting changing and automatically toggle itself. But this works. + Command.toggle(on = false) + } + return@setOnPreferenceChangeListener true + } + updatePrefs() } diff --git a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt new file mode 100644 index 00000000..cc6dc9fe --- /dev/null +++ b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt @@ -0,0 +1,57 @@ +package com.jmstudios.redmoon.service + +import android.accessibilityservice.AccessibilityService +import android.animation.ValueAnimator +import android.graphics.PixelFormat +import android.view.View +import android.view.WindowManager +import android.view.accessibility.AccessibilityEvent +import com.jmstudios.redmoon.* +import com.jmstudios.redmoon.helper.Logger +import org.greenrobot.eventbus.Subscribe + + +class AccessibilityFilterService : AccessibilityService() { + lateinit var mFilter: Overlay + + override fun onAccessibilityEvent(event: AccessibilityEvent) {} + override fun onInterrupt() {} + + override fun onServiceConnected() { + instance = this; + enabled = true; + mFilter = Overlay(applicationContext) + val lp = WindowManager.LayoutParams().apply { + type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY + format = PixelFormat.TRANSLUCENT + flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE.or(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + } + (getSystemService(WINDOW_SERVICE) as WindowManager).addView(mFilter, lp) + + mFilter.visibility = View.GONE; + + EventBus.register(this) + } + + override fun onDestroy() { + super.onDestroy() + EventBus.unregister(this); + enabled = false; + } + + @Subscribe + fun turnOnOrOff(cmd: accessibilityServiceCommand) { + Log.i("${cmd.command}") + mFilter.setBackgroundColor(activeProfile.filterColor) + mFilter.visibility = if (cmd.command.turnOn) View.VISIBLE else View.GONE + } + + companion object : Logger() { + var enabled = false; + lateinit var instance: AccessibilityFilterService + } + +// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { +// return super.onStartCommand(intent, flags, startId) +// } +} diff --git a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt index 0e9f1a4c..b17acb75 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt @@ -30,26 +30,13 @@ import android.app.Service import android.content.Intent import android.os.IBinder import android.widget.Toast +import com.jmstudios.redmoon.* import java.util.concurrent.Executors -import com.jmstudios.redmoon.activeProfile -import com.jmstudios.redmoon.Command -import com.jmstudios.redmoon.CommandAnimatorListener -import com.jmstudios.redmoon.Config -import com.jmstudios.redmoon.EventBus -import com.jmstudios.redmoon.Filter -import com.jmstudios.redmoon.filterIsOn import com.jmstudios.redmoon.filter.surfaceflinger.SurfaceFlinger import com.jmstudios.redmoon.helper.Logger import com.jmstudios.redmoon.helper.Permission import com.jmstudios.redmoon.manager.CurrentAppMonitor -import com.jmstudios.redmoon.Notification -import com.jmstudios.redmoon.Overlay -import com.jmstudios.redmoon.overlayPermissionDenied -import com.jmstudios.redmoon.Profile -import com.jmstudios.redmoon.ProfileEvaluator -import com.jmstudios.redmoon.R -import com.jmstudios.redmoon.secureSuspendChanged import org.greenrobot.eventbus.Subscribe import com.topjohnwu.superuser.Shell @@ -107,6 +94,11 @@ class FilterService : Service() { Config.useRoot = false; stopForeground(false) } + } else if (Config.useAccessibilityService) { + EventBus.post(accessibilityServiceCommand(Command.getCommand(intent))) + filterIsOn = Command.getCommand(intent).turnOn + mCurrentAppMonitor.monitoring = Command.getCommand(intent).turnOn && Config.secureSuspend + Log.i("$filterIsOn") } else { if (Permission.Overlay.isGranted) { fadeInOrOut() @@ -138,12 +130,16 @@ class FilterService : Service() { filterIsOn = false mCurrentAppMonitor.monitoring = false } + if(Config.useAccessibilityService) { + EventBus.post(accessibilityServiceCommand(Command.OFF)) + } mFilter.onDestroy() executor.shutdownNow() super.onDestroy() } @Subscribe fun onProfileUpdated(profile: Profile) { + Log.i("onProfileUpdated") mFilter.profile = profile startForeground(NOTIFICATION_ID, mNotification.build(true)) } diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 3b09924d..6e487c29 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -26,6 +26,7 @@ pref_key_use_root + pref_key_use_accessibility_service pref_key_profile_spinner pref_key_shades_dim_level pref_key_shades_intensity_level diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 788d986e..bed62000 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -202,4 +202,7 @@ Overlay Control The persistent overlay control notification + Red Moon Overlay + Use Accessibiltiy Service + Cover the home screen (Android 12+) and status/navigation bars (Android 10+) diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 3f89bae3..bafd0650 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -63,6 +63,15 @@ android:summary="@string/pref_summary_use_root" /> + + Date: Wed, 14 Sep 2022 21:18:29 -0400 Subject: [PATCH 02/10] Use whether the svc is on in system settings as source of truth --- .../main/java/com/jmstudios/redmoon/Config.kt | 2 - .../main/java/com/jmstudios/redmoon/Util.kt | 7 ++++ .../redmoon/fragment/SettingsFragment.kt | 38 ++++--------------- .../service/AccessibilityFilterService.kt | 4 -- .../redmoon/service/FilterService.kt | 4 +- app/src/main/res/xml/settings.xml | 10 ++--- 6 files changed, 21 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/jmstudios/redmoon/Config.kt b/app/src/main/java/com/jmstudios/redmoon/Config.kt index 57c3e682..54cc57c0 100644 --- a/app/src/main/java/com/jmstudios/redmoon/Config.kt +++ b/app/src/main/java/com/jmstudios/redmoon/Config.kt @@ -203,8 +203,6 @@ object Config : Preferences(appContext) { } var useRoot by BooleanPreference(R.string.pref_key_use_root, false) - - var useAccessibilityService by BooleanPreference(R.string.pref_key_use_accessibility_service, false) //endregion //region application diff --git a/app/src/main/java/com/jmstudios/redmoon/Util.kt b/app/src/main/java/com/jmstudios/redmoon/Util.kt index 7667d7ed..ad17d021 100644 --- a/app/src/main/java/com/jmstudios/redmoon/Util.kt +++ b/app/src/main/java/com/jmstudios/redmoon/Util.kt @@ -24,7 +24,9 @@ */ package com.jmstudios.redmoon +import android.content.Context import android.content.Intent +import android.provider.Settings import androidx.preference.Preference import androidx.core.content.ContextCompat import androidx.preference.PreferenceFragmentCompat @@ -60,6 +62,11 @@ var filterIsOn: Boolean = false Config.filterIsOn = value } +fun isAccessibilityServiceOn(context: Context?): Boolean { + val prefString = Settings.Secure.getString(context?.contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) + return prefString != null && prefString.contains("com.jmstudios.redmoon.service.AccessibilityFilterService") +} + fun inActivePeriod(Log: KLog? = null): Boolean { val now = Calendar.getInstance() diff --git a/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt b/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt index 599a6a3f..4ebcc615 100644 --- a/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt @@ -16,23 +16,11 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference import com.google.android.material.snackbar.Snackbar -import com.jmstudios.redmoon.Command +import com.jmstudios.redmoon.* -import com.jmstudios.redmoon.Config -import com.jmstudios.redmoon.EventBus -import com.jmstudios.redmoon.filterIsOn -import com.jmstudios.redmoon.getColor import com.jmstudios.redmoon.helper.Logger import com.jmstudios.redmoon.helper.Permission -import com.jmstudios.redmoon.inActivePeriod -import com.jmstudios.redmoon.locationAccessDenied -import com.jmstudios.redmoon.locationChanged -import com.jmstudios.redmoon.locationService -import com.jmstudios.redmoon.pref -import com.jmstudios.redmoon.R -import com.jmstudios.redmoon.scheduleChanged import com.jmstudios.redmoon.service.LocationUpdateService -import com.jmstudios.redmoon.useLocationChanged import com.topjohnwu.superuser.Shell import org.greenrobot.eventbus.Subscribe @@ -59,8 +47,8 @@ class SettingsFragment : PreferenceFragmentCompat() { private val rootPref: SwitchPreference get() = pref(R.string.pref_key_use_root) as SwitchPreference - private val accessibilityServicePref: SwitchPreference - get() = pref(R.string.pref_key_use_accessibility_service) as SwitchPreference + private val accessibilityServicePref: Preference + get() = pref(R.string.pref_key_use_accessibility_service) as Preference private var mSnackbar: Snackbar? = null @@ -126,24 +114,12 @@ class SettingsFragment : PreferenceFragmentCompat() { return@setOnPreferenceChangeListener true } - accessibilityServicePref.setOnPreferenceChangeListener { _, newValue -> + accessibilityServicePref.setOnPreferenceClickListener { _ -> // Make sure root is available before enabling - if (newValue as Boolean) { - val prefString = Settings.Secure.getString(context?.contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) - Log.i("FOO 20 FOO 10 ${context?.contentResolver } $prefString") - if(prefString == null || !prefString.contains("com.jmstudios.redmoon.service.AccessibilityFilterService")) { - startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)); - return@setOnPreferenceChangeListener false - } + if(!isAccessibilityServiceOn(context)) { + startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)) } - if (filterIsOn) { - // It would be better to toggle back on again using the new mode but it's more work - // to add that, since the filter service needs to restart, so we need to wait until - // the fade-out finishes to start again. Or maybe better, the filter service could - // listen for this setting changing and automatically toggle itself. But this works. - Command.toggle(on = false) - } - return@setOnPreferenceChangeListener true + return@setOnPreferenceClickListener true } updatePrefs() diff --git a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt index cc6dc9fe..584a663a 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt @@ -50,8 +50,4 @@ class AccessibilityFilterService : AccessibilityService() { var enabled = false; lateinit var instance: AccessibilityFilterService } - -// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { -// return super.onStartCommand(intent, flags, startId) -// } } diff --git a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt index b17acb75..28c198a5 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt @@ -94,7 +94,7 @@ class FilterService : Service() { Config.useRoot = false; stopForeground(false) } - } else if (Config.useAccessibilityService) { + } else if (isAccessibilityServiceOn(applicationContext)) { EventBus.post(accessibilityServiceCommand(Command.getCommand(intent))) filterIsOn = Command.getCommand(intent).turnOn mCurrentAppMonitor.monitoring = Command.getCommand(intent).turnOn && Config.secureSuspend @@ -130,7 +130,7 @@ class FilterService : Service() { filterIsOn = false mCurrentAppMonitor.monitoring = false } - if(Config.useAccessibilityService) { + if(isAccessibilityServiceOn(applicationContext)) { EventBus.post(accessibilityServiceCommand(Command.OFF)) } mFilter.onDestroy() diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index bafd0650..e33b36de 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -63,14 +63,14 @@ android:summary="@string/pref_summary_use_root" /> - + > + + Date: Wed, 14 Sep 2022 21:54:08 -0400 Subject: [PATCH 03/10] Make it work with "Next Filter" and pause buttons --- app/src/main/java/com/jmstudios/redmoon/Command.kt | 1 - .../com/jmstudios/redmoon/service/FilterService.kt | 11 ++++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/jmstudios/redmoon/Command.kt b/app/src/main/java/com/jmstudios/redmoon/Command.kt index 335a41e0..c2f999fd 100644 --- a/app/src/main/java/com/jmstudios/redmoon/Command.kt +++ b/app/src/main/java/com/jmstudios/redmoon/Command.kt @@ -105,7 +105,6 @@ enum class Command(val time: Float) { fun getCommand(intent: Intent): Command { val commandName = intent.getStringExtra(EXTRA_COMMAND) ?: "" - Log.i("Recieved flag: $commandName") return valueOf(commandName) } diff --git a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt index 28c198a5..369e5a65 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt @@ -70,7 +70,7 @@ class FilterService : Service() { } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - Log.i("onStartCommand($intent, $flags, $startId)") + Log.i("onStartCommand($intent, ${Command.getCommand(intent)}, $flags, $startId)") fun fadeInOrOut() { val cmd = Command.getCommand(intent) val end = if (cmd.turnOn) activeProfile else mFilter.profile.off @@ -96,9 +96,10 @@ class FilterService : Service() { } } else if (isAccessibilityServiceOn(applicationContext)) { EventBus.post(accessibilityServiceCommand(Command.getCommand(intent))) - filterIsOn = Command.getCommand(intent).turnOn mCurrentAppMonitor.monitoring = Command.getCommand(intent).turnOn && Config.secureSuspend Log.i("$filterIsOn") + Command.getCommand(intent).onAnimationStart(this@FilterService) + Command.getCommand(intent).onAnimationEnd(this@FilterService) } else { if (Permission.Overlay.isGranted) { fadeInOrOut() @@ -140,7 +141,11 @@ class FilterService : Service() { @Subscribe fun onProfileUpdated(profile: Profile) { Log.i("onProfileUpdated") - mFilter.profile = profile + if(isAccessibilityServiceOn(applicationContext)) { + EventBus.post(accessibilityServiceCommand(Command.ON)) + } else { + mFilter.profile = profile + } startForeground(NOTIFICATION_ID, mNotification.build(true)) } From 47ac3f809da266811a8ced68f1ae175dd847b3b2 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Wed, 14 Sep 2022 22:16:14 -0400 Subject: [PATCH 04/10] Update string per testing on Android <=11 :( --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bed62000..70cb40c3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -204,5 +204,5 @@ The persistent overlay control notification Red Moon Overlay Use Accessibiltiy Service - Cover the home screen (Android 12+) and status/navigation bars (Android 10+) + Enable to cover up the home screen and status/navigation bars on Android 12+ From 81552b6821dcc4f53ba80a478b2b2812143d05b2 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Wed, 14 Sep 2022 22:31:44 -0400 Subject: [PATCH 05/10] Add accessibility service description and fix the link when it's on --- app/src/main/AndroidManifest.xml | 3 +++ .../jmstudios/redmoon/fragment/SettingsFragment.kt | 5 +---- .../redmoon/service/AccessibilityFilterService.kt | 9 --------- app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/accessibility_service_config.xml | 11 +++++++++++ 5 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 app/src/main/res/xml/accessibility_service_config.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5dab121b..395382c7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -162,6 +162,9 @@ + + diff --git a/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt b/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt index 4ebcc615..002f4e31 100644 --- a/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/jmstudios/redmoon/fragment/SettingsFragment.kt @@ -115,10 +115,7 @@ class SettingsFragment : PreferenceFragmentCompat() { } accessibilityServicePref.setOnPreferenceClickListener { _ -> - // Make sure root is available before enabling - if(!isAccessibilityServiceOn(context)) { - startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)) - } + startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)) return@setOnPreferenceClickListener true } diff --git a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt index 584a663a..ff69285d 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt @@ -18,8 +18,6 @@ class AccessibilityFilterService : AccessibilityService() { override fun onInterrupt() {} override fun onServiceConnected() { - instance = this; - enabled = true; mFilter = Overlay(applicationContext) val lp = WindowManager.LayoutParams().apply { type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY @@ -36,18 +34,11 @@ class AccessibilityFilterService : AccessibilityService() { override fun onDestroy() { super.onDestroy() EventBus.unregister(this); - enabled = false; } @Subscribe fun turnOnOrOff(cmd: accessibilityServiceCommand) { - Log.i("${cmd.command}") mFilter.setBackgroundColor(activeProfile.filterColor) mFilter.visibility = if (cmd.command.turnOn) View.VISIBLE else View.GONE } - - companion object : Logger() { - var enabled = false; - lateinit var instance: AccessibilityFilterService - } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 70cb40c3..bb299c42 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -205,4 +205,5 @@ Red Moon Overlay Use Accessibiltiy Service Enable to cover up the home screen and status/navigation bars on Android 12+ + On Android 12 or greater, this service lets Red Moon draw over the notification shade, home screen, and navigation buttons. On lower versions of Android, this service isn\'t necessary, so you should leave it off. diff --git a/app/src/main/res/xml/accessibility_service_config.xml b/app/src/main/res/xml/accessibility_service_config.xml new file mode 100644 index 00000000..4de5da2f --- /dev/null +++ b/app/src/main/res/xml/accessibility_service_config.xml @@ -0,0 +1,11 @@ + + From 70a2f7f9fddc266becf558919dab59f80a1fced2 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Thu, 15 Sep 2022 02:21:57 -0400 Subject: [PATCH 06/10] Unify LayoutParams and draw over cutouts --- .../java/com/jmstudios/redmoon/Overlay.kt | 52 +++++--- .../redmoon/manager/ScreenManager.kt | 119 ------------------ .../service/AccessibilityFilterService.kt | 11 +- 3 files changed, 40 insertions(+), 142 deletions(-) delete mode 100644 app/src/main/java/com/jmstudios/redmoon/manager/ScreenManager.kt diff --git a/app/src/main/java/com/jmstudios/redmoon/Overlay.kt b/app/src/main/java/com/jmstudios/redmoon/Overlay.kt index ea0e92d2..212b6bb8 100644 --- a/app/src/main/java/com/jmstudios/redmoon/Overlay.kt +++ b/app/src/main/java/com/jmstudios/redmoon/Overlay.kt @@ -25,13 +25,16 @@ package com.jmstudios.redmoon import android.content.Context +import android.content.res.Resources import android.graphics.Canvas +import android.graphics.PixelFormat +import android.os.Build import android.view.View +import android.view.WindowInsets import android.view.WindowManager import com.jmstudios.redmoon.helper.Logger import com.jmstudios.redmoon.manager.BrightnessManager -import com.jmstudios.redmoon.manager.ScreenManager import com.jmstudios.redmoon.receiver.OrientationChangeReceiver import kotlin.properties.Delegates @@ -42,7 +45,6 @@ class Overlay(context: Context) : View(context), Filter, OrientationChangeReceiver.OnOrientationChangeListener { private val mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager - private val mScreenManager = ScreenManager(context, mWindowManager) private val mOrientationReceiver = OrientationChangeReceiver(context, this) private val mBrightnessManager = BrightnessManager(context) @@ -71,7 +73,6 @@ class Overlay(context: Context) : View(context), Filter, } private fun show() { - updateLayoutParams() mWindowManager.addView(this, mLayoutParams) mBrightnessManager.brightnessLowered = profile.lowerBrightness mOrientationReceiver.register() @@ -93,18 +94,40 @@ class Overlay(context: Context) : View(context), Filter, mBrightnessManager.brightnessLowered = profile.lowerBrightness } - private var mLayoutParams = mScreenManager.layoutParams - get() = field.apply { - buttonBrightness = Config.buttonBacklightLevel - type = if (atLeastAPI(26)) { - WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - } else { - WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY - } + val mLayoutParams = WindowManager.LayoutParams().apply { + buttonBrightness = Config.buttonBacklightLevel + // TODO: why is cutout always null? + // if(atLeastAPI(Build.VERSION_CODES.P)) { + // val cutout = WindowInsets.Builder().build().displayCutout + // val top = cutout?.boundingRectTop?.height() ?: 0 + // val bottom = cutout?.boundingRectBottom?.height() ?: 0 + // val left = cutout?.boundingRectLeft?.width() ?: 0 + // val right = cutout?.boundingRectRight?.width() ?: 0 + // height = Resources.getSystem().displayMetrics.heightPixels + top + bottom + // width = Resources.getSystem().displayMetrics.widthPixels + left + right + // x = -left + // y = -top + // } else { + height = Resources.getSystem().displayMetrics.heightPixels + 4000 + width = Resources.getSystem().displayMetrics.widthPixels + 4000 + x = -1000 + y = -1000 + // } + format = PixelFormat.TRANSLUCENT + type = if (isAccessibilityServiceOn(context) && atLeastAPI(Build.VERSION_CODES.M)) { + WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY + } else if (atLeastAPI(Build.VERSION_CODES.O)) { + WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY + } else { + WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY + } + flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + .or(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + .or(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) + .or(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES } - - private fun updateLayoutParams() { - mLayoutParams = mScreenManager.layoutParams } private fun reLayout() = mWindowManager.updateViewLayout(this, mLayoutParams) @@ -112,7 +135,6 @@ class Overlay(context: Context) : View(context), Filter, override fun onDraw(canvas: Canvas) = canvas.drawColor(profile.filterColor) override fun onOrientationChanged() { - updateLayoutParams() reLayout() } diff --git a/app/src/main/java/com/jmstudios/redmoon/manager/ScreenManager.kt b/app/src/main/java/com/jmstudios/redmoon/manager/ScreenManager.kt deleted file mode 100644 index cf51e349..00000000 --- a/app/src/main/java/com/jmstudios/redmoon/manager/ScreenManager.kt +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2017 Stephen Michel - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (c) 2015 Chris Nguyen - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice appear - * in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -package com.jmstudios.redmoon.manager - -import android.content.Context -import android.content.res.Configuration -import android.content.res.Resources -import android.graphics.PixelFormat -import android.util.DisplayMetrics -import android.util.TypedValue -import android.view.Gravity -import android.view.WindowManager - -import com.jmstudios.redmoon.helper.Logger - -private const val DEFAULT_NAV_BAR_HEIGHT_DP = 48 -private const val DEFAULT_STATUS_BAR_HEIGHT_DP = 25 - -class ScreenManager(context: Context, private val mWindowManager: WindowManager) { - - private val mResources: Resources = context.resources - private var mStatusBarHeight = -1 - private var mNavigationBarHeight = -1 - - val layoutParams: WindowManager.LayoutParams - get() = WindowManager.LayoutParams( - WindowManager.LayoutParams.MATCH_PARENT, - screenHeight, - 0, - -statusBarHeightPx, - WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE - or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS - or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR - or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, - PixelFormat.TRANSLUCENT - ).apply { - gravity = Gravity.TOP or Gravity.START - } - - val screenHeight: Int - get() { - val display = mWindowManager.defaultDisplay - val dm = DisplayMetrics() - display.getRealMetrics(dm) - return if (inPortrait) { - dm.heightPixels + statusBarHeightPx + navigationBarHeightPx - } else { - dm.heightPixels + statusBarHeightPx - } - } - - val statusBarHeightPx: Int - get() { - if (mStatusBarHeight == -1) { - val statusBarHeightId = mResources.getIdentifier("status_bar_height", "dimen", "android") - - if (statusBarHeightId > 0) { - mStatusBarHeight = mResources.getDimensionPixelSize(statusBarHeightId) - Log.i("Found Status Bar Height: " + mStatusBarHeight) - } else { - mStatusBarHeight = dpToPx(DEFAULT_STATUS_BAR_HEIGHT_DP) - Log.i("Using default Status Bar Height: " + mStatusBarHeight) - } - } - - return mStatusBarHeight - } - - val navigationBarHeightPx: Int - get() { - if (mNavigationBarHeight == -1) { - val navBarHeightId = mResources.getIdentifier("navigation_bar_height", "dimen", "android") - - if (navBarHeightId > 0) { - mNavigationBarHeight = mResources.getDimensionPixelSize(navBarHeightId) - Log.i("Found Navigation Bar Height: " + mNavigationBarHeight) - } else { - mNavigationBarHeight = dpToPx(DEFAULT_NAV_BAR_HEIGHT_DP) - Log.i("Using default Navigation Bar Height: " + mNavigationBarHeight) - } - } - - return mNavigationBarHeight - } - - private fun dpToPx(dp: Int): Int { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - dp.toFloat(), mResources.displayMetrics).toInt() - } - - private val inPortrait: Boolean - get() = mResources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT - - companion object : Logger() -} diff --git a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt index ff69285d..608da985 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt @@ -4,6 +4,7 @@ import android.accessibilityservice.AccessibilityService import android.animation.ValueAnimator import android.graphics.PixelFormat import android.view.View +import android.view.ViewGroup import android.view.WindowManager import android.view.accessibility.AccessibilityEvent import com.jmstudios.redmoon.* @@ -19,20 +20,14 @@ class AccessibilityFilterService : AccessibilityService() { override fun onServiceConnected() { mFilter = Overlay(applicationContext) - val lp = WindowManager.LayoutParams().apply { - type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY - format = PixelFormat.TRANSLUCENT - flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE.or(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) - } - (getSystemService(WINDOW_SERVICE) as WindowManager).addView(mFilter, lp) - + (getSystemService(WINDOW_SERVICE) as WindowManager).addView(mFilter, mFilter.mLayoutParams) mFilter.visibility = View.GONE; - EventBus.register(this) } override fun onDestroy() { super.onDestroy() + (getSystemService(WINDOW_SERVICE) as WindowManager).removeView(mFilter) EventBus.unregister(this); } From 6e17911ed1a9aa576f7ac603ee3eca149662acae Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 17 Sep 2022 20:03:20 -0400 Subject: [PATCH 07/10] Code review feedback & remove unneeded stuff --- app/src/main/java/com/jmstudios/redmoon/Overlay.kt | 2 +- .../jmstudios/redmoon/service/AccessibilityFilterService.kt | 4 ++-- .../main/java/com/jmstudios/redmoon/service/FilterService.kt | 1 - app/src/main/res/xml/settings.xml | 2 -- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/jmstudios/redmoon/Overlay.kt b/app/src/main/java/com/jmstudios/redmoon/Overlay.kt index 212b6bb8..850b8954 100644 --- a/app/src/main/java/com/jmstudios/redmoon/Overlay.kt +++ b/app/src/main/java/com/jmstudios/redmoon/Overlay.kt @@ -125,7 +125,7 @@ class Overlay(context: Context) : View(context), Filter, .or(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) .or(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) .or(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (atLeastAPI(Build.VERSION_CODES.P)) { layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES } } diff --git a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt index 608da985..492e459f 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/AccessibilityFilterService.kt @@ -26,9 +26,9 @@ class AccessibilityFilterService : AccessibilityService() { } override fun onDestroy() { - super.onDestroy() - (getSystemService(WINDOW_SERVICE) as WindowManager).removeView(mFilter) EventBus.unregister(this); + (getSystemService(WINDOW_SERVICE) as WindowManager).removeView(mFilter) + super.onDestroy() } @Subscribe diff --git a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt index 369e5a65..38cf5aa6 100644 --- a/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt +++ b/app/src/main/java/com/jmstudios/redmoon/service/FilterService.kt @@ -97,7 +97,6 @@ class FilterService : Service() { } else if (isAccessibilityServiceOn(applicationContext)) { EventBus.post(accessibilityServiceCommand(Command.getCommand(intent))) mCurrentAppMonitor.monitoring = Command.getCommand(intent).turnOn && Config.secureSuspend - Log.i("$filterIsOn") Command.getCommand(intent).onAnimationStart(this@FilterService) Command.getCommand(intent).onAnimationEnd(this@FilterService) } else { diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index e33b36de..acbe58fe 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -68,8 +68,6 @@ android:title="@string/pref_title_use_accessibility_service" android:summary="@string/pref_summary_use_accessibility_service" > - Date: Sat, 17 Sep 2022 20:05:11 -0400 Subject: [PATCH 08/10] Remove one more unused thing --- app/src/main/res/xml/accessibility_service_config.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/xml/accessibility_service_config.xml b/app/src/main/res/xml/accessibility_service_config.xml index 4de5da2f..af5f60bf 100644 --- a/app/src/main/res/xml/accessibility_service_config.xml +++ b/app/src/main/res/xml/accessibility_service_config.xml @@ -7,5 +7,4 @@ android:accessibilityFeedbackType="feedbackVisual" android:notificationTimeout="100" android:canRetrieveWindowContent="false" - android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" /> From f24ae9e7641602a75f9ff5ae80f287422d729f50 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 24 Sep 2022 02:28:48 -0400 Subject: [PATCH 09/10] Fix embarrassing typo --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bb299c42..e2eeb9a6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -203,7 +203,7 @@ Overlay Control The persistent overlay control notification Red Moon Overlay - Use Accessibiltiy Service + Use Accessibility Service Enable to cover up the home screen and status/navigation bars on Android 12+ On Android 12 or greater, this service lets Red Moon draw over the notification shade, home screen, and navigation buttons. On lower versions of Android, this service isn\'t necessary, so you should leave it off. From 5a9b03617c6d3dc87683b09b5393e386f7e5a4c3 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Fri, 23 Feb 2024 00:23:36 -0500 Subject: [PATCH 10/10] Remove unused and build-blocking test classes --- .../java/com/jmstudios/redmoon/ApplicationTest.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/androidTest/java/com/jmstudios/redmoon/ApplicationTest.kt b/app/src/androidTest/java/com/jmstudios/redmoon/ApplicationTest.kt index 97b62ffe..2b39e21d 100644 --- a/app/src/androidTest/java/com/jmstudios/redmoon/ApplicationTest.kt +++ b/app/src/androidTest/java/com/jmstudios/redmoon/ApplicationTest.kt @@ -14,11 +14,3 @@ ** SOFTWARE. */ package com.jmstudios.redmoon - -import android.app.Application -import android.test.ApplicationTestCase - -/** - * [Testing Fundamentals](http://d.android.com/tools/testing/testing_android.html) - */ -class ApplicationTest : ApplicationTestCase(Application::class.java)