Skip to content

Notification panel constraint#2150

Closed
keymapper-ai wants to merge 43 commits into
developfrom
claude/issue-1980-notification-panel-constraint
Closed

Notification panel constraint#2150
keymapper-ai wants to merge 43 commits into
developfrom
claude/issue-1980-notification-panel-constraint

Conversation

@keymapper-ai

Copy link
Copy Markdown
Collaborator

Closes #1980

Summary

  • Added two new constraints: "Notification panel is showing" and "Notification panel is not showing", placed in the Display category.
  • Detection is implemented in BaseAccessibilityService via the getWindows() API: the service checks whether any TYPE_SYSTEM accessibility window has a root node belonging to com.android.systemui and visible to the user. This fires on every TYPE_WINDOWS_CHANGED accessibility event.
  • The detection state is exposed as isNotificationShadeExpanded: Flow<Boolean> on IAccessibilityService, integrated into LazyConstraintSnapshot, and wired up as a new NOTIFICATION_PANEL_STATE dependency.
  • Strings, icons (Notifications / NotificationsOff), entity constants, mapper, comparator, and TestConstraintSnapshot all updated to cover the new entries.

Known limitations / areas for human review

  • Best-effort detection: As noted in the issue discussion with @sds100, there is no 100% reliable way to detect the notification panel on all devices. On stock Android the approach works well, but heavily customised OEMs (e.g. Samsung OneUI) may expose additional TYPE_SYSTEM windows from com.android.systemui that cause a false positive even when the shade is collapsed. Manual testing on target devices is recommended.
  • The constraint is labelled generically ("Notification panel is showing") to cover both the notification shade and quick-settings panel, consistent with the direction agreed in the issue.
  • The onDependencyChanged(NOTIFICATION_PANEL_STATE) path is wired up but, like other dependencies, is currently only exercised if a caller subscribes to it.

Test plan

  • Build and install a debug APK on a stock Android device
  • Create a key map with the "Notification panel is showing" constraint and verify it only triggers when the shade is expanded
  • Create a key map with the "Notification panel is not showing" constraint and verify it triggers when the shade is closed
  • Verify no regression on existing constraints (screen on/off, keyboard showing, lock screen)
  • Test on at least one Samsung device to check for false positives from OEM customisation

Generated by Claude Code

claude and others added 30 commits May 31, 2026 00:16
…d 13+

Adds ic_launcher_monochrome.xml using evenOdd fill paths derived from the
existing foreground icon so the DPad and keyboard shapes are recognisable
in a single colour. Updates all adaptive-icon XML files (release, debug, ci)
to reference the new monochrome layer.
Add two new constraints — "Notification panel is showing" and "Notification panel is not
showing" — that allow key maps to be conditional on whether the Android status bar /
notification shade is expanded.

Detection is implemented via the AccessibilityService window list: a TYPE_SYSTEM window
whose root node belongs to com.android.systemui and is visible to the user is treated as
evidence that the notification shade is expanded. This is a best-effort heuristic;
accuracy may vary across OEMs and Android versions, as acknowledged in issue discussion.
fix: Support email string formatting fix
Move the debugging section (GetEvent button) inside the
`warningState is Understood` conditional so it is only visible
after the user acknowledges the expert mode warning, preventing
the bypass via the debug screen.

Also add a defensive guard in ExpertModeViewModel.onGetEventClick()
that returns early if the warning has not been acknowledged.
…ug-screen-on-expert-warning

Expert mode warning can be bypassed by going via expert mode debug screen
…t be found because there are many different package names out there

Closes #2156
…guard

Fix Direct Boot accessibility startup
… setting screen

When the system bridge is connected (expert mode), the choose setting
screen now queries the Settings ContentProvider directly through a new
getAllSettings() AIDL method instead of falling back to the restricted
ContentProvider query from the app process.

The system bridge runs with shell/root privileges, giving it access to
all settings rows that the app process cannot see. A queryCompat helper
is added to IContentProviderUtils to handle the version-dependent
IContentProvider.query() signatures across API 29–34+. When the system
bridge is not connected, the existing ContentResolver query is used as
a fallback.
…-list-expert-mode

Listing settings for modify setting action should use `settings list` for expert mode users
ktlint requires imports to be in lexicographic order; Notifications and
NotificationsOff were appended after StopCircle instead of their correct
position between MobileOff and PlayArrow.
sds100 and others added 13 commits June 24, 2026 10:28
Add three new constraints to check the current ringer mode: Ring, Vibrate,
and Silent. These appear in the Phone category of the constraint picker.

- Add RINGER_MODE_NORMAL, RINGER_MODE_VIBRATE, RINGER_MODE_SILENT to ConstraintId
- Add corresponding ConstraintData sealed objects and entity mapping
- Add ringerModeFlow to VolumeAdapter, implemented via BroadcastReceiver for
  AudioManager.RINGER_MODE_CHANGED_ACTION in AndroidVolumeAdapter
- Wire VolumeAdapter into LazyConstraintSnapshot and DetectConstraintsUseCase
- Add RINGER_MODE to ConstraintDependency
- Add UI strings, icons, and titles
- Update TestConstraintSnapshot with ringerMode field
…a class

Use ConstraintData.RingerMode(val ringerMode: RingerMode) instead of three
separate data objects (RingerModeNormal/Vibrate/Silent), following the
OrientationCustom pattern. Entity backward compatibility is preserved via
the existing three entity type strings.
…erMode field

Replace three separate data objects (RingerModeNormal, RingerModeVibrate, RingerModeSilent)
with one data class ConstraintData.RingerMode(ringerMode: SystemRingerMode), following the
OrientationCustom pattern. DB entity backward compatibility is preserved via three separate
entity type strings. Add @serializable to RingerMode enum for kotlinx.serialization support.
Fix exhaustive when expressions in ChooseConstraintViewModel and KeyMapConstraintsComparator.
…ode-constraints

#2163 feat: add ringer mode constraints (Ring, Vibrate, Silent)
Add two new constraints — "Notification panel is showing" and "Notification panel is not
showing" — that allow key maps to be conditional on whether the Android status bar /
notification shade is expanded.

Detection is implemented via the AccessibilityService window list: a TYPE_SYSTEM window
whose root node belongs to com.android.systemui and is visible to the user is treated as
evidence that the notification shade is expanded. This is a best-effort heuristic;
accuracy may vary across OEMs and Android versions, as acknowledged in issue discussion.
ktlint requires imports to be in lexicographic order; Notifications and
NotificationsOff were appended after StopCircle instead of their correct
position between MobileOff and PlayArrow.
…anel-constraint' into claude/issue-1980-notification-panel-constraint
@sds100 sds100 closed this Jul 9, 2026
@sds100 sds100 deleted the claude/issue-1980-notification-panel-constraint branch July 9, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Notification panel constraint

6 participants