CVE-2025-22417 AI-generated analysis
platform/frameworks/base, WindowManager (services/core/java/com/android/server/wm/Transition.java, shell transitions / ActivityRecordInputSink)
In Transition.finishTransition (services/core/java/com/android/server/wm/Transition.java), the ActivityRecordInputSink (touch-blocking) state of visible participant activities is now written into each activity's pending transaction and flushed via scheduleAnimationLocked(), instead of being applied immediately through a freshly created standalone SurfaceControl.Transaction, to fix a race that could leave the state stale.
Root cause
After a transition finished, Transition.java allocated a new SurfaceControl.Transaction via ar.mWmService.mTransactionFactory.get(), called ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged() on it for every visible ActivityRecord participant, and applied it immediately. Per the commit message, when finishTransition ran before the pending transaction had been applied, the result could be a stale state. Because the InputWindowHandle is only applied on changes, a later prepareSurfaces pass did not fix it, so the incorrect input-sink state persisted.
How the fix works
- services/core/java/com/android/server/wm/Transition.java, finishTransition (the block commented 'Update the input-sink (touch-blocking) state now that the animation is finished'): removes the local SurfaceControl.Transaction inputSinkTransaction created from ar.mWmService.mTransactionFactory.get() and its immediate inputSinkTransaction.apply().
- For each participant where ar != null && ar.isVisible() && ar.getParent() != null, calls ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(ar.getPendingTransaction()) so the input-sink change is queued in that container's pending transaction.
- Sets a boolean scheduleAnimation and, if any participant was updated, calls mController.mAtm.mWindowManager.scheduleAnimationLocked() ('To apply pending transactions') so the pending transactions get applied, rather than relying on a separate apply.
Completeness
- Covers only the finishTransition path in Transition.java and only ActivityRecord participants; it changes where the input-sink update is queued, not the applyChangesToSurfaceIfChanged 'only on change' semantics.
- Flushing now depends on scheduleAnimationLocked() causing the pending transactions to be applied; the fix does not add any explicit apply of the pending transaction itself.
- The code at android-security-14.0.0_r29 shows the same block extended to also update task.mTaskInputSink via task.getPendingTransaction() for visible Task participants; that Task path is not part of this commit's diff.
- Other callers of ActivityRecordInputSink.applyChangesToSurfaceIfChanged are not shown in the material and are not touched by this commit.
Behavior changes
- Input-sink (touch-blocking) surface updates at the end of a transition are deferred to the application of pending transactions instead of being applied synchronously in finishTransition.
- finishTransition now calls scheduleAnimationLocked() whenever at least one visible, attached ActivityRecord participant exists.
- No new SurfaceControl.Transaction is allocated via mTransactionFactory in this path.
Per major
- Android 14: same fix: commit 89e32320207c in android-security-14.0.0_r19 (DO NOT MERGE cherry-pick, Change-Id If93840ad7b2abbcb48c0c332870c48046c0f8fdc). At android-security-14.0.0_r29 the block also handles task.mTaskInputSink (3/8 patched lines present), still using getPendingTransaction() and scheduleAnimationLocked().
- Android 15: same fix: commit d0c52fbde587 in android-security-15.0.0_r7, identical hunk at a different offset (line 1398). At android-security-15.0.0_r17 3/8 lines of the patched region are present; the code there is not shown.
- Android 16: not affected per the bulletin; at android-security-16.0.0_r8 3/8 lines of the patched region are present (code not shown in the material).
- Android 17: not affected per the bulletin; at android-security-17.0.0_r1 3/8 lines of the patched region are present (code not shown in the material).
Unknowns
- The concrete user-visible consequence of the stale input-sink state and the POC steps referenced in the commit message (Bug 332277530) are not in the material.
- Whether other callers of applyChangesToSurfaceIfChanged use a standalone transaction with the same ordering issue is not shown.
- The exact Transition.java content at the Android 15 r17, 16 and 17 security tags is not shown; only the 3/8 line-match count is given.
- When the Task input-sink branch seen at 14.0.0_r29 was introduced is not shown.