[AppSupport] Android app window hidden ("app_closed_by_android") during activity transition while task is still alive and visible

REPRODUCIBILITY: Frequent (race condition, roughly every 2nd–3rd attempt)
OS VERSION: 5.2.0.20
HARDWARE: Jolla Phone (2026)
UI LANGUAGE: Norwegian (nb_NO)
REGRESSION: Unknown

DESCRIPTION:

When an Android app finishes its root activity and starts a new activity a few milliseconds later, the AppSupport window manager (ALIEN in surfaceflinger) concludes that the app has closed and hides its window. The app cover also disappears. On the Android side the task is still alive, focused and visible=true, with the new activity resumed, so the app keeps running “invisibly”.
This is a common pattern (splash/login → dashboard), so many apps are likely affected. I see it consistently with Handelsbanken Norway (com.handelsbanken.mobile.android.nopriv), which in practice makes the app unusable: it appears to “crash” right after PIN login.

PRECONDITIONS:

  • Android AppSupport running
  • An app that calls finish() on its root activity and then starts a new activity (here: LoginActivity → DashboardActivity)

STEPS TO REPRODUCE:

  1. Open Handelsbanken and log in with PIN

  2. Watch the app window after the PIN is accepted

EXPECTED RESULT:

The dashboard is shown.

ACTUAL RESULT:

The app window disappears (as if crashed) and the cover is gone. The app is in fact still running and logged in.
Log (the window is hidden 42 ms before the next activity starts, in the same task):

16:27:36.967 surfaceflinger: ALIEN: app_closed_by_android: com.handelsbanken.mobile.android.nopriv:76
16:27:36.967 surfaceflinger: APPSUPPORT: hiding window: com.handelsbanken.mobile.android.nopriv
16:27:37.009 ActivityTaskManager: START u0 {cmp=.../com.evry.mobile.android.lib.dashboard.DashboardActivity} (BAL_ALLOW_GRACE_PERIOD)
16:27:37.581 ActivityTaskManager: Displayed .../DashboardActivity for user 0: +585ms

Android state afterwards (dumpsys activity activities): the task is alive, focused and visible:

* Task{bd4e928 #119 type=standard A=10063:com.handelsbanken.mobile.android.nopriv visible=true visibleRequested=true mode=fullscreen}
  topResumedActivity=ActivityRecord{... DashboardActivity t119}
  topDisplayFocusedRootTask=Task{bd4e928 #119 ...}

Consequence 2 – session lost on relaunch: Because the cover is gone, the only way back is the launcher icon. That sends a new MAIN intent with LAUNCH_SINGLE_TASK, which clears the task and restarts the app from scratch, so the running (logged-in) session is thrown away:

16:27:40.361 ActivityTaskManager: START u0 {act=android.intent.action.MAIN ... StartupActivity} with LAUNCH_SINGLE_TASK
16:27:40.759 ActivityTaskManager: Displayed .../PinActivity

WORKAROUND (confirms the cause):
Any task move event makes ALIEN find the task again. Running the following as root brings the hidden window back immediately, with the app still logged in:

appsupport-attach am start -a android.intent.action.MAIN -c android.intent.category.HOME
23:57:40.570 surfaceflinger: RECOVERING UNKNOWN TASK: 119 com.handelsbanken.mobile.android.nopriv
23:57:40.570 surfaceflinger: ALIEN: MOVED KNOWN TASK: 119 0 com.handelsbanken.mobile.android.nopriv
23:57:40.614 surfaceflinger: APPSUPPORT: Show com.handelsbanken.mobile.android.nopriv

I currently run a small watchdog that listens for app_closed_by_android and triggers the HOME intent if the task is still visible=true. That works, but it is obviously a workaround.
SUGGESTED FIX:

  • Do not treat a task as closed while the Android task still exists. Debounce app_closed_by_android (e.g. 300–500 ms) and check that the task is actually gone/invisible before hiding the window and removing the cover, or
  • When a new activity appears in a task ALIEN has marked as closed, automatically re-raise it (the same thing the RECOVERING UNKNOWN TASK path already does, just triggered on activity start instead of a task move).

MODIFICATIONS:

  • Patchmanager: no
  • OpenRepos: yes (Storeman)
  • Chum: yes
  • Other: microG in AppSupport

ADDITIONAL INFORMATION:

Probably reproducible with a minimal test app: an Activity A (root) that in onClick calls startActivity(B) from a background thread/handler after finish(), or finish() followed immediately by startActivity(B). Full logs available on request.

1 Like