CVE-2025-48570 AI-generated analysis
platform/frameworks/base, WindowManager Shell PiP (libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java)
The fix adds a 3-second check to PipTaskOrganizer#onTaskAppeared in WM Shell: if no PiP-entering transition state change follows a pinned task appearing (the commit attributes this to a SystemUI reboot), tasks whose top activity matches that component are removed.
Root cause
When SystemUI restarts, PipTaskOrganizer#onTaskAppeared can get a pinned task with no PiP enter transition after it. Before the fix, nothing detected or removed such a stale pinned task, so it stayed in place. The commit's test line ("make sure no background Activity launch") ties this state to a background Activity launch.
How the fix works
- PipTaskOrganizer.java adds CRASH_RECOVERY_CHECK_DELAY_MS = 3000 and a field, mRemoveStaledPinnedTaskRunnable.
- PipTaskOrganizer#onTaskAppeared builds a runnable and posts it with mMainExecutor.executeDelayed after 3000 ms. The runnable reads info.topActivity, calls ActivityTaskManager.getService().getTasks(10, false, false, Display.DEFAULT_DISPLAY), and calls removeTask(taskId) on every task whose topActivity matches. A RemoteException is logged.
- The PipTaskOrganizer constructor registers an OnPipTransitionStateChangedListener on mPipTransitionState. When mPipTransitionState.isEnteringPip() is true, it removes the pending runnable from mMainExecutor and clears it, so a normal PiP entry cancels the cleanup.
- Commit history: original 670f2df6bf5e (android-security-14.0.0_r24); revert 94929458bc26 (reason b/458676344); reland c0f88bec3bf0, which adds null checks on info and info.topActivity (addressing the NPE in b/459832318), returns early if null, and logs the component. The reland is the final form.
Completeness
- The cleanup is a timeout heuristic. It only fires if no transition state reaches isEnteringPip within 3 s.
- Only the first 10 tasks returned by getTasks for Display.DEFAULT_DISPLAY are checked. A stale pinned task on another display, or outside those 10, is not removed.
- Tasks are matched by topActivity ComponentName, not by task id or windowing mode. Any non-PiP task with the same top activity among those 10 would also be removed.
- If onTaskAppeared runs again before the timeout, the field is overwritten without cancelling the earlier posted runnable, so that one still runs.
- The fix is entirely in WM Shell. No change to system_server task or activity-start code appears in this material.
Behavior changes
- About 3 s after a pinned task appears with no PiP-entering transition state change following, the shell removes tasks whose top activity matches that component and logs "SystemUI reboot detected, remove staled PiP task %s". Nothing is removed if info or info.topActivity is null.
- Extra binder calls (getTasks and removeTask) from SystemUI to ActivityTaskManager.
Per major
- Android 14: Fixed. Original commit 670f2df6bf5e in android-security-14.0.0_r24; its revert (94929458bc26) and the reland with null checks (c0f88bec3bf0) are both in android-security-14.0.0_r28. All 8 lines of the patched region are present at r29.
- Android 15: Not affected per the bulletin (not listed). All 8 lines of the patched region are present at android-security-15.0.0_r17.
- Android 16: Not affected per the bulletin (not listed). All 8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: Not affected per the bulletin (not listed). All 8 lines of the patched region are present at android-security-17.0.0_r1.
Unknowns
- The exact attack trigger and how the stale pinned task leads to a background activity launch.
- The content of b/458676344, the reason for the revert.
- Why Android 15 to 17 are not affected, given that the patched-region lines are present there.
- Whether any fix was also made on the server (system_server) side.