CVE-2026-28656 AI-generated analysis
platform/frameworks/base (services/autofill UI: AutoFillUI, FillUi, SaveUi, DialogFillUi, OverlayControl), platform/packages/apps/Settings (DeviceAdminAdd), platform/packages/apps/Car/Settings (DeviceAdminAddActivity, DeviceAdminAddHeaderPreferenceController), platform/packages/apps/TvSettings (DeviceAdminAdd)
Replaces the AppOps user-restriction based overlay suppression (OP_SYSTEM_ALERT_WINDOW / OP_TOAST_WINDOW toggled on show/hide or resume/pause) with the window-level Window#setHideOverlayWindows(true) / SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS flag. The change covers the autofill UI (FillUi, SaveUi, DialogFillUi) and the DeviceAdminAdd screens in Settings, Car Settings and TvSettings.
Root cause
Sensitive UIs protected themselves with AppOpsManager.setUserRestriction / setUserRestrictionForUser(OP_SYSTEM_ALERT_WINDOW and OP_TOAST_WINDOW, true, token). These UIs are the autofill fill, save and dialog UI in system_server, plus the device-admin activation screen in Settings, Car Settings and TvSettings. The restriction was set when the UI was shown (autofill OverlayControl.hideOverlays after show) or resumed (DeviceAdminAdd onResume), and cleared when the UI was hidden, destroyed or paused. Per the commit messages, this approach "didn't stop overlay window showing again without SYSTEM_ALERT_WINDOW permission when the restrictions are released". The protection was a system-wide AppOps toggle tied to lifecycle and show/hide calls, not a property of the protected window. Autofill applied it with UserHandle.USER_ALL.
How the fix works
- frameworks/base c441211a26c9: services/autofill/java/com/android/server/autofill/ui/OverlayControl.java is deleted. It was the AppOps setUserRestrictionForUser wrapper for OP_SYSTEM_ALERT_WINDOW / OP_TOAST_WINDOW with USER_ALL.
- AutoFillUI.java: the mOverlayControl field and its construction in the AutoFillUI constructor are removed. The OverlayControl argument is dropped from the FillUi, SaveUi and DialogFillUi constructor calls. Per index search, DialogFillUi is created in showFillDialog.
- FillUi.java: the FillUi constructor and the AnchoredWindow constructor lose the OverlayControl parameter. In AnchoredWindow's show path, `params.privateFlags |= SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS` is set before the if (!mShowing) branch, so it applies to both the addView branch and the else branch. The mOverlayControl.hideOverlays() call after addView is removed, and so is the finally { showOverlays() } in the block that handles destroyCallbackOnError.
- DialogFillUi.java: the constructor loses the OverlayControl parameter and calls `mDialog.getWindow().setHideOverlayWindows(true)` right after mDialog.setContentView(decor). show(), hide() and destroy() no longer toggle overlays through AppOps, and the try/finally wrappers are removed.
- SaveUi.java: the constructor loses the OverlayControl parameter. In the dialog window setup, `window.setHideOverlayWindows(true)` is added after window.setCloseOnTouchOutside(true). show(), hide() and destroy() no longer call hideOverlays/showOverlays.
- packages/apps/Settings e115f7703748 (Android 14) and f6b6ecb4b6e1 (Android 16): DeviceAdminAdd.onCreate replaces `mAppOps = getSystemService(AppOpsManager.class)` with `getWindow().setHideOverlayWindows(true)`. The setUserRestriction(true) calls in onResume and the setUserRestriction(false) calls in onPause are removed, along with the mAppOps field and the AppOpsManager import.
- packages/apps/Car/Settings ccb13e0864d4: DeviceAdminAddActivity gains an onCreate override that calls `getWindow().setHideOverlayWindows(true)` after super.onCreate. DeviceAdminAddHeaderPreferenceController drops mAppOps and mToken, and the setUserRestriction calls in onResumeInternal and onPauseInternal.
- packages/apps/TvSettings 7a21141ea7ef (Android 15 tag): DeviceAdminAdd.onCreate replaces the AppOpsManager lookup with `getWindow().setHideOverlayWindows(true)`. mToken, mAppOps and the onResume/onPause setUserRestriction calls are removed.
Completeness
- All three autofill UI surfaces in frameworks/base are converted. FillUi (AnchoredWindow) gets the flag through privateFlags on its LayoutParams. DialogFillUi and SaveUi get it through Window#setHideOverlayWindows on the Dialog window. OverlayControl is deleted, so no autofill caller is left on the AppOps path.
- The device-admin activation screens are converted in Settings (DeviceAdminAdd), Car Settings (DeviceAdminAddActivity) and TvSettings (DeviceAdminAdd). The TvSettings change appears only in the Android 15 tag material.
- The flag is now set when the window is created (constructor, dialog setup or onCreate) instead of being toggled on show/hide or resume/pause.
- The old code also restricted OP_TOAST_WINDOW, while the new code only sets the hide-non-system-overlay flag. The material does not show whether that flag also suppresses toast windows.
- In Settings DeviceAdminAdd, the android.os.Binder / IBinder imports are still present after the fix, and the diff does not remove the mToken field. This is leftover code, not a functional gap.
- In Car Settings, DeviceAdminAddHeaderPreferenceController.onPauseInternal keeps preference.setEnabled(false), which its comment describes as preventing tapjacking.
- The material does not show whether other system UIs still use the AppOps setUserRestriction(OP_SYSTEM_ALERT_WINDOW) pattern.
Behavior changes
- While the autofill fill UI, save UI or fill dialog, or a DeviceAdminAdd screen is visible, its window carries the hide-non-system-overlay flag, so non-system overlay windows are hidden (per the semantics of Window#setHideOverlayWindows).
- These UIs no longer set an AppOps user restriction on OP_SYSTEM_ALERT_WINDOW / OP_TOAST_WINDOW when they appear. In the autofill case that restriction applied to USER_ALL.
- These components no longer restrict toast windows explicitly through OP_TOAST_WINDOW.
- With the try/finally blocks removed, hide() and destroy() in SaveUi and DialogFillUi no longer make AppOps calls on teardown.
Per major
- Android 14: same fix: resolved at android-security-14.0.0_r29 by three commits linked through bug 463364901: frameworks/base c441211a26c9 (autofill UI, OverlayControl deleted), packages/apps/Settings e115f7703748 (DeviceAdminAdd) and packages/apps/Car/Settings ccb13e0864d4 (DeviceAdminAddActivity and header controller). Only 6/8 lines of the patched region are reported present at that tag. The material shows no TvSettings commit for 14.
- Android 15: same fix: resolved at android-security-15.0.0_r17. The material shows packages/apps/TvSettings 7a21141ea7ef, where DeviceAdminAdd.onCreate calls getWindow().setHideOverlayWindows(true) and the AppOps calls are removed. 8/8 lines of the patched region are present.
- Android 16: same fix: resolved at android-security-16.0.0_r8. The material shows packages/apps/Settings f6b6ecb4b6e1, the same content as the Android 14 Settings change. 8/8 lines are present.
- Android 17: not affected: per the per-major facts, the bulletin does not list Android 17. 6/8 lines of the patched region are present at android-security-17.0.0_r1. The material shows no fix commit for 17.
Unknowns
- The exact sequence by which an overlay could appear over the protected UI under the old AppOps scheme. The commit message only says the restriction did not stop overlays from showing again once it was released.
- Whether the new flag also covers toast windows previously blocked through OP_TOAST_WINDOW.
- Which 2 of the 8 patched-region lines are missing at android-security-14.0.0_r29 and android-security-17.0.0_r1, and whether a TvSettings fix exists for Android 14.
- The bulletin/OSV affected list includes '17-next', while the per-major facts treat Android 17 as not listed. That discrepancy is not resolved by the material.
- Whether Car Settings and TvSettings hold the permission needed for setHideOverlayWindows on a given fork.