diff --git a/app/src/main/java/io/timelimit/android/data/model/ConfigurationItem.kt b/app/src/main/java/io/timelimit/android/data/model/ConfigurationItem.kt index 59294b8..d4d2577 100644 --- a/app/src/main/java/io/timelimit/android/data/model/ConfigurationItem.kt +++ b/app/src/main/java/io/timelimit/android/data/model/ConfigurationItem.kt @@ -250,4 +250,5 @@ object ExperimentalFlags { const val SYNC_RELATED_NOTIFICATIONS = 32768L const val INSTANCE_ID_FG_APP_DETECTION = 65536L // private const val OBSOLETE_DISABLE_FG_APP_DETECTION_FALLBACK = 131072L + const val STRICT_OVERLAY_CHECKING = 0x40000L } \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt b/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt index 39ffd59..7a649da 100644 --- a/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt +++ b/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt @@ -36,7 +36,7 @@ abstract class PlatformIntegration( abstract fun getLauncherAppPackageName(): String? abstract fun getCurrentProtectionLevel(): ProtectionLevel abstract fun getForegroundAppPermissionStatus(): RuntimePermissionStatus - abstract fun getDrawOverOtherAppsPermissionStatus(): RuntimePermissionStatus + abstract fun getDrawOverOtherAppsPermissionStatus(strictChecking: Boolean): RuntimePermissionStatus abstract fun getNotificationAccessPermissionStatus(): NewPermissionStatus abstract fun isAccessibilityServiceEnabled(): Boolean abstract fun disableDeviceAdmin() diff --git a/app/src/main/java/io/timelimit/android/integration/platform/android/AndroidIntegration.kt b/app/src/main/java/io/timelimit/android/integration/platform/android/AndroidIntegration.kt index 1ac09e5..4574c0b 100644 --- a/app/src/main/java/io/timelimit/android/integration/platform/android/AndroidIntegration.kt +++ b/app/src/main/java/io/timelimit/android/integration/platform/android/AndroidIntegration.kt @@ -173,7 +173,7 @@ class AndroidIntegration(context: Context): PlatformIntegration(maximumProtectio Toast.makeText(context, text, Toast.LENGTH_SHORT).show() } - override fun getDrawOverOtherAppsPermissionStatus(): RuntimePermissionStatus = overlay.getOverlayPermissionStatus() + override fun getDrawOverOtherAppsPermissionStatus(strictChecking: Boolean): RuntimePermissionStatus = overlay.getOverlayPermissionStatus(strictChecking) override fun getNotificationAccessPermissionStatus(): NewPermissionStatus { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -761,7 +761,7 @@ class AndroidIntegration(context: Context): PlatformIntegration(maximumProtectio } SystemPermission.Overlay -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if ( - overlay.getOverlayPermissionStatus() == RuntimePermissionStatus.NotGranted && + overlay.getOverlayPermissionStatus(true) == RuntimePermissionStatus.NotGranted && confirmationLevel == SystemPermissionConfirmationLevel.None ) { PermissionInfoConfirmDialog.newInstance(SystemPermission.Overlay) diff --git a/app/src/main/java/io/timelimit/android/integration/platform/android/OverlayUtil.kt b/app/src/main/java/io/timelimit/android/integration/platform/android/OverlayUtil.kt index 0cf4d89..73a6e69 100644 --- a/app/src/main/java/io/timelimit/android/integration/platform/android/OverlayUtil.kt +++ b/app/src/main/java/io/timelimit/android/integration/platform/android/OverlayUtil.kt @@ -43,7 +43,7 @@ class OverlayUtil(private var application: Application) { return } - if (getOverlayPermissionStatus() == RuntimePermissionStatus.NotGranted) { + if (getOverlayPermissionStatus(false) == RuntimePermissionStatus.NotGranted) { return } @@ -89,15 +89,15 @@ class OverlayUtil(private var application: Application) { fun isOverlayShown() = currentView?.root?.isShown ?: false - fun getOverlayPermissionStatus() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - if (checkAppOp() || Settings.canDrawOverlays(application)) + fun getOverlayPermissionStatus(strictChecking: Boolean) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + if (checkAppOp(strictChecking) || Settings.canDrawOverlays(application)) RuntimePermissionStatus.Granted else RuntimePermissionStatus.NotGranted else RuntimePermissionStatus.NotRequired - private fun checkAppOp(): Boolean { + private fun checkAppOp(strictChecking: Boolean): Boolean { if (systemOverlayOp == null) return false val mode1 = AppOps.getOpMode(systemOverlayOp, appsOpsManager, application) @@ -108,6 +108,7 @@ class OverlayUtil(private var application: Application) { val mode2 = appsOpsManager.checkOpNoThrow(systemOverlayOp, Process.myUid(), application.packageName) - return mode2 == AppOpsManager.MODE_ALLOWED || mode2 == AppOpsManager.MODE_IGNORED + return if (strictChecking) mode2 == AppOpsManager.MODE_ALLOWED + else mode2 == AppOpsManager.MODE_ALLOWED || mode2 == AppOpsManager.MODE_IGNORED } } \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/integration/platform/dummy/DummyIntegration.kt b/app/src/main/java/io/timelimit/android/integration/platform/dummy/DummyIntegration.kt index 79fcf8d..4fc14a6 100644 --- a/app/src/main/java/io/timelimit/android/integration/platform/dummy/DummyIntegration.kt +++ b/app/src/main/java/io/timelimit/android/integration/platform/dummy/DummyIntegration.kt @@ -68,7 +68,7 @@ class DummyIntegration( return foregroundAppPermission } - override fun getDrawOverOtherAppsPermissionStatus(): RuntimePermissionStatus { + override fun getDrawOverOtherAppsPermissionStatus(strictChecking: Boolean): RuntimePermissionStatus { return drawOverOtherApps } diff --git a/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt b/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt index bee964a..a324278 100644 --- a/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt +++ b/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt @@ -874,6 +874,7 @@ class BackgroundTaskLogic(val appLogic: AppLogic) { private suspend fun getUpdateDeviceStatusAction(): UpdateDeviceStatusAction { val deviceEntry = appLogic.deviceEntry.waitForNullableValue() + val useStrictChecking = appLogic.database.config().isExperimentalFlagsSetAsync(ExperimentalFlags.STRICT_OVERLAY_CHECKING).waitForNonNullValue() var changes = UpdateDeviceStatusAction.empty @@ -881,7 +882,7 @@ class BackgroundTaskLogic(val appLogic: AppLogic) { val protectionLevel = appLogic.platformIntegration.getCurrentProtectionLevel() val usageStatsPermission = appLogic.platformIntegration.getForegroundAppPermissionStatus() val notificationAccess = appLogic.platformIntegration.getNotificationAccessPermissionStatus() - val overlayPermission = appLogic.platformIntegration.getDrawOverOtherAppsPermissionStatus() + val overlayPermission = appLogic.platformIntegration.getDrawOverOtherAppsPermissionStatus(useStrictChecking) val accessibilityService = appLogic.platformIntegration.isAccessibilityServiceEnabled() val qOrLater = AndroidVersion.qOrLater diff --git a/app/src/main/java/io/timelimit/android/ui/diagnose/DiagnoseExperimentalFlagFragment.kt b/app/src/main/java/io/timelimit/android/ui/diagnose/DiagnoseExperimentalFlagFragment.kt index c276200..34bc2f9 100644 --- a/app/src/main/java/io/timelimit/android/ui/diagnose/DiagnoseExperimentalFlagFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/diagnose/DiagnoseExperimentalFlagFragment.kt @@ -201,6 +201,12 @@ data class DiagnoseExperimentalFlagItem( enableFlags = ExperimentalFlags.INSTANCE_ID_FG_APP_DETECTION, disableFlags = ExperimentalFlags.INSTANCE_ID_FG_APP_DETECTION, enable = { true } + ), + DiagnoseExperimentalFlagItem( + label = R.string.diagnose_exf_soc, + enableFlags = ExperimentalFlags.STRICT_OVERLAY_CHECKING, + disableFlags = ExperimentalFlags.STRICT_OVERLAY_CHECKING, + enable = { true } ) ) } diff --git a/app/src/main/java/io/timelimit/android/ui/setup/SetupDevicePermissionsFragment.kt b/app/src/main/java/io/timelimit/android/ui/setup/SetupDevicePermissionsFragment.kt index 08e6ee5..7077c12 100644 --- a/app/src/main/java/io/timelimit/android/ui/setup/SetupDevicePermissionsFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/setup/SetupDevicePermissionsFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2021 Jonas Lochmann + * TimeLimit Copyright 2019 - 2022 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -106,7 +106,7 @@ class SetupDevicePermissionsFragment : Fragment() { binding.notificationAccessPermission = platform.getNotificationAccessPermissionStatus() binding.protectionLevel = platform.getCurrentProtectionLevel() binding.usageStatsAccess = platform.getForegroundAppPermissionStatus() - binding.overlayPermission = platform.getDrawOverOtherAppsPermissionStatus() + binding.overlayPermission = platform.getDrawOverOtherAppsPermissionStatus(true) binding.accessibilityServiceEnabled = platform.isAccessibilityServiceEnabled() } diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d253c66..4d7e205 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -530,6 +530,7 @@ Overlay und Home-Button nicht zum Sperren verwenden Toasts zur Synchronisation anzeigen neue App-Erkennungs-Methode verwenden + strengere Prüfung der Überlagerungs-Berechtigung aktivieren Hintergrundaufgabenschleifenfehler diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e478d4e..3d71cc3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -583,6 +583,7 @@ Do not use a overlay or the home button for blocking Show sync related toasts Use new App detection method + Enable strict overlay permission check Background task loop exception