Skip to content

Commit

Permalink
Merge pull request #74 from akaMrNagar/dev
Browse files Browse the repository at this point in the history
Fix: Multiple overlays makes device unresponsive
  • Loading branch information
akaMrNagar authored Mar 5, 2025
2 parents 009b698 + 01e17b2 commit d79fad9
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ class DeviceLockUnlockReceiver(
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
Intent.ACTION_USER_PRESENT -> {
onDeviceLockChanged.invoke(true)
Log.d(TAG, "onDeviceUnlocked: User UNLOCKED the device and device is ACTIVE")
onDeviceLockChanged.invoke(true)
}

Intent.ACTION_SCREEN_OFF -> {
onDeviceLockChanged.invoke(false)
Log.d(TAG, "onDeviceLocked: User LOCKED the device and device is INACTIVE")
onDeviceLockChanged.invoke(false)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import com.mindful.android.helpers.device.PermissionsHelper
import com.mindful.android.helpers.storage.SharedPrefsHelper
import com.mindful.android.models.WellBeingSettings
import com.mindful.android.receivers.DeviceAppsChangedReceiver
import com.mindful.android.receivers.alarm.MidnightResetReceiver
import com.mindful.android.utils.AppConstants.FACEBOOK_PACKAGE
import com.mindful.android.utils.AppConstants.INSTAGRAM_PACKAGE
import com.mindful.android.utils.AppConstants.REDDIT_PACKAGE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,9 @@ class TrackingManager(

@WorkerThread
fun onNewEvent(packageName: String) {
if (lastActiveApp != packageName) {
if (lastActiveApp != packageName && !ignoredPackages.contains(packageName)) {
lastActiveApp = packageName

// only send broadcast if packages are not ignored
if (!ignoredPackages.contains(packageName)) {
broadcastEvent(ACTION_NEW_APP_LAUNCHED)
}
broadcastEvent(ACTION_NEW_APP_LAUNCHED)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.mindful.android.services.tracking

import android.accessibilityservice.AccessibilityService
import android.app.Service.USAGE_STATS_SERVICE
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
Expand All @@ -13,6 +12,7 @@ import android.util.Log
import androidx.annotation.MainThread
import androidx.annotation.WorkerThread
import com.mindful.android.receivers.DeviceLockUnlockReceiver
import com.mindful.android.services.accessibility.MindfulAccessibilityService
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_NEW_APP_LAUNCHED
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_START_MANUAL_TRACKING
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_STOP_MANUAL_TRACKING
Expand Down Expand Up @@ -75,8 +75,6 @@ class LaunchTrackingManager(
context.registerReceiver(accessibilityReceiver, accessibilityFilter)
}

// Check if accessibility is already running
isManualTrackingOn = !Utils.isServiceRunning(context, AccessibilityService::class.java)

// Start tracking
onDeviceUnlocked()
Expand All @@ -85,6 +83,10 @@ class LaunchTrackingManager(

@MainThread
private fun onDeviceUnlocked() {
// Check if accessibility is already running
isManualTrackingOn =
!Utils.isServiceRunning(context, MindfulAccessibilityService::class.java)

// Start tracking manually only if accessibility is not running
if (isManualTrackingOn) {
// First cancel earlier task if already not cancelled
Expand All @@ -100,15 +102,18 @@ class LaunchTrackingManager(
)

Log.d(TAG, "onDeviceUnlocked: Manual usage tracking started")
Thread { broadcastLastAppLaunchEvent() }.start()
}

Thread { broadcastLastAppLaunchEvent() }.start()
}

@MainThread
private fun onDeviceLocked() {
trackingExecutor?.shutdownNow()
trackingExecutor = null

// To cancel reminders and remove overlay
onNewAppLaunched.invoke("com.android.systemui")
Log.d(TAG, "onDeviceLocked: Manual usage tracking stopped")
}

Expand Down Expand Up @@ -200,7 +205,10 @@ class LaunchTrackingManager(

ACTION_NEW_APP_LAUNCHED -> intent.getStringExtra(AppConstants.INTENT_EXTRA_PACKAGE_NAME)
?.let {
Thread { onNewAppLaunched.invoke(it) }.start()
Thread {
lastLaunchedApp = it
broadcastLastAppLaunchEvent()
}.start()
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,21 @@ class MindfulTrackerService : Service() {

fun onMidnightReset() {
restrictionManager.resetCache()
overlayManager.dismissOverlay()
// overlayManager.dismissOverlay()
// reminderManager.cancelReminders()
}


@WorkerThread
private fun onNewAppLaunch(packageName: String) {
try {
Log.d(TAG, "onNewAppLaunch: $packageName launched")

/// Cancel previous reminders and dismiss overlay
reminderManager.cancelReminders()
overlayManager.dismissOverlay()

/// check current restrictions
val currentOrFutureState = restrictionManager.isAppRestricted(packageName)
val currentOrFutureState = restrictionManager.isAppRestricted(packageName)

Log.d(TAG, "onNewAppLaunch: $packageName's evaluated state $currentOrFutureState")
currentOrFutureState?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import android.widget.ProgressBar
import android.widget.TextView
import androidx.annotation.MainThread
import com.mindful.android.R
import com.mindful.android.models.RestrictionState
import com.mindful.android.enums.RestrictionType
import com.mindful.android.models.RestrictionState
import com.mindful.android.utils.ThreadUtils
import com.mindful.android.utils.Utils

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,23 @@ import com.mindful.android.R
import com.mindful.android.helpers.device.NotificationHelper
import com.mindful.android.models.RestrictionState
import com.mindful.android.utils.ThreadUtils
import java.util.Stack

class OverlayManager(
private val context: Context,
) {
private val windowManager: WindowManager =
context.getSystemService(WINDOW_SERVICE) as WindowManager

private var overlay: View? = null
private var isDismissingOverlay: Boolean = false
private var overlays: Stack<View> = Stack()


init {
fadeOutAnim.setAnimationListener(
object : Animation.AnimationListener {
override fun onAnimationStart(a: Animation?) {
isDismissingOverlay = true
}

override fun onAnimationStart(a: Animation?) {}
override fun onAnimationRepeat(a: Animation?) {}

override fun onAnimationEnd(a: Animation?) {
isDismissingOverlay = false
removeOverlay()
}
}
Expand All @@ -47,22 +43,16 @@ class OverlayManager(

/// Animate out the overlay
fun dismissOverlay() {
/// Skip if already animating to dismiss
if (isDismissingOverlay) {
return
}

if (overlays.isEmpty()) return
ThreadUtils.runOnMainThread {
animateOverlay(animateIn = false)
animateOverlay(overlay = overlays.peek(), animateIn = false)
}
}

/// Remove overlay after animating out
/// Remove overlay instantly
private fun removeOverlay() {
overlay?.let {
windowManager.removeView(it)
overlay = null
}
if (overlays.isEmpty()) return
windowManager.removeView(overlays.pop())
}


Expand All @@ -71,8 +61,10 @@ class OverlayManager(
restrictionState: RestrictionState,
addReminderDelay: ((futureMinutes: Int) -> Unit)? = null,
) {
Log.d(TAG, "showOverlay: Showing overlay for $packageName")
// Return if overlay is not null
if (overlays.isNotEmpty()) return

Log.d(TAG, "showOverlay: Showing overlay for $packageName")
ThreadUtils.runOnMainThread {
// Notify, stop and return if don't have overlay permission
if (!Settings.canDrawOverlays(context)) {
Expand All @@ -85,7 +77,7 @@ class OverlayManager(
}

// Build overlay
overlay = OverlayBuilder.buildOverlay(
val overlay = OverlayBuilder.buildOverlay(
context,
packageName,
restrictionState,
Expand All @@ -111,24 +103,23 @@ class OverlayManager(

// TODO: Fix the deprecated logic
// Full screen edge to edge view
overlay?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
overlay.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY


// Add the overlay view to the window
layoutParams.gravity = Gravity.TOP or Gravity.START
windowManager.addView(overlay, layoutParams)
overlay?.rotation = 0f
overlay?.findViewById<FrameLayout>(R.id.overlay_root)?.rotation = 0f
overlays.push(overlay)

// Animate the overlay
animateOverlay(animateIn = true)
animateOverlay(overlay = overlay, animateIn = true)
}
}

private fun animateOverlay(animateIn: Boolean) {
overlay?.let { view ->
private fun animateOverlay(overlay: View, animateIn: Boolean) {
overlay.let { view ->
// Find the layers within overlay view
val bgLayer = view.findViewById<View>(R.id.overlay_background)
val sheetLayer = view.findViewById<LinearLayout>(R.id.overlay_sheet)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ class ReminderManager(
state: RestrictionState,
) {
// If it is a timer restricted state
if (state.usedScreenTime > 0
&& state.totalScreenTimer > 0
&& ((state.totalScreenTimer - state.usedScreenTime) > 120)
) {
if ((state.totalScreenTimer - state.usedScreenTime) > 120) {
reminderTriggers.add(1)
}

Expand All @@ -48,10 +45,9 @@ class ReminderManager(

Log.d(
TAG,
"onTick: $spentMins Minute ticked with reminders: $reminderTriggers"
"onTick: Elapsed $spentMins minutes with reminders: $reminderTriggers"
)


if (reminderTriggers.contains(spentMins)) {
reminderTriggers.remove(spentMins)
overlayManager.showOverlay(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,30 +205,30 @@ class RestrictionManager(

/// Check for app timer
if (restriction.timerSec > 0) {
val screenTime: Long = screenUsage[restriction.appPackage] ?: 0
val screenTimeSec: Long = screenUsage[restriction.appPackage] ?: 0

/// App timer ran out
if (screenTime >= restriction.timerSec) {
if (screenTimeSec >= restriction.timerSec) {
Log.d(TAG, "evaluateScreenTimeLimit: App's timer is over")
val state = RestrictionState(
message = context.getString(R.string.app_paused_reason_app_timer_out),
type = RestrictionType.Timer,
expirationFutureMs = -1L,
usedScreenTime = screenTime,
usedScreenTime = screenTimeSec,
totalScreenTimer = restriction.timerSec.toLong(),
)

alreadyRestrictedApps[restriction.appPackage] = state
return state
} else {
/// App timer left so add expiration timestamp
val leftAppLimitMs = (restriction.timerSec - screenTime) * 1000L
val leftAppLimitMs = (restriction.timerSec - screenTimeSec) * 1000L
futureStates.add(
RestrictionState(
message = context.getString(R.string.app_paused_reason_app_timer_left),
type = RestrictionType.Timer,
expirationFutureMs = leftAppLimitMs,
usedScreenTime = screenTime,
usedScreenTime = screenTimeSec,
totalScreenTimer = restriction.timerSec.toLong(),
)
)
Expand All @@ -244,10 +244,10 @@ class RestrictionManager(
}

if (group.timerSec > 0) {
val groupScreenTime = group.distractingApps.sumOf { screenUsage[it] ?: 0 }
val groupScreenTimeSec = group.distractingApps.sumOf { screenUsage[it] ?: 0 }

/// group timer ran out
if (groupScreenTime >= group.timerSec) {
if (groupScreenTimeSec >= group.timerSec) {
Log.d(TAG, "evaluateScreenTimeLimit: App's timer is over")
val state = RestrictionState(
message = context.getString(
Expand All @@ -256,15 +256,15 @@ class RestrictionManager(
),
type = RestrictionType.Timer,
expirationFutureMs = -1L,
usedScreenTime = groupScreenTime,
usedScreenTime = groupScreenTimeSec,
totalScreenTimer = group.timerSec.toLong(),
)

alreadyRestrictedGroups[group.id] = state
return state
} else {
/// group timer left so add expiration timestamp
val leftAppLimitMs = (group.timerSec - groupScreenTime) * 1000L
val leftAppLimitMs = (group.timerSec - groupScreenTimeSec) * 1000L
futureStates.add(
RestrictionState(
message = context.getString(
Expand All @@ -273,7 +273,7 @@ class RestrictionManager(
),
type = RestrictionType.Timer,
expirationFutureMs = leftAppLimitMs,
usedScreenTime = groupScreenTime,
usedScreenTime = groupScreenTimeSec,
totalScreenTimer = group.timerSec.toLong(),
)
)
Expand Down

0 comments on commit d79fad9

Please sign in to comment.