Repository navigation
Conversation
… the curated nine Android-only. Replaces the curated 9-app notification catalog with live on-device discovery: an App Notifications page listing every user-installed app that can post notifications, each with its own enable switch, buzz pattern, and test button. - NotifierAppDiscovery merges installed apps declaring POST_NOTIFICATIONS (via an intent-shaped <queries> entry - no QUERY_ALL_PACKAGES) with every package the listener has seen post; FLAG_SYSTEM filtered on both paths. Package names only, on-device, no notification content read. - Per-app prefs reuse the existing keys, so discovered apps buzz exactly like curated ones and inherit the quiet-hours and only-when-worn rules unchanged. - Notifications page: redundant category cards removed, App Notifications section after Calls, header pill counts every persisted opt-in. - App Notifications page: catch-all at top with the mutual-exclusion explanation, opted-in apps pinned above search, scanning placeholder, real launcher icons. - Delivery note shows the Notification Access grant live; mirror buzz written acknowledged (ryanbr#921 lesson). - All new copy extracted across the 9 gated locales. Refs ryanbr#168, ryanbr#1115, ryanbr#921
…kable - drop FLAG_SYSTEM on the discovered path only
… rows - the switch alone carries the state
|
Approved the workflow runs, so this has now been through CI and all four checks are green. The parts I expected to be delicate check out. The manifest addition really is the narrow query you describe, a MAIN/LAUNCHER shaped Three things to send back, plus one question. 1. The CHANGELOG section
2. Three unreferenced screenshots
3. The acknowledged buzz belongs in its own changeI went looking for this as an undeclared change and it is not one: it is in the body, in the checklist, and in The questionThe Notifications page drops the Email, Messaging, Meetings and Calendar category cards on the grounds that the picker covers them. Per-app prefs reuse The feature itself is one people have asked for and the discovery approach is the right one. These are all things to settle before it lands, not objections to the shape of it. |
Release sections are generated from docs/releases/vX.Y.Z.md by Tools/appchangelog-gen.py at release time, so a hand-written heading collides; and 12.0.1 is not next (main is 12.1.0, test beta cut at 555/436). The prose lives on in the PR description for whoever writes notes for the version that carries this.
The picker screenshots were PR illustrations, not repo assets: docs/screenshots does not exist on main, nothing on the branch references them, and a notifier-app picker screenshot permanently archives whatever was installed on the phone it was taken on. Stripped originals move to a fork assets branch for the PR body.
buzz -> buzzAcknowledged alters what goes over the radio on every mirrored notification, in a PR whose subject is a settings screen, and the justification is the ryanbr#921 hypothesis, not a measurement that a without-response write was dropped. Confirmed writes cost a GATT round trip on a strap family with a drain history (ryanbr#1120/ryanbr#1144/ryanbr#1197/ryanbr#1198). The picker lands with the bare write; the acknowledged write ships separately with drop evidence attached, so a later drain move has one variable to look at.
…the buzz rhythm The category cards applied a per-category default pattern (Messaging = Single, Email/Calendar = Double, Meetings = Triple) to opted-in apps that never picked one; nothing was persisted for them. The picker's package-keyed read defaults to Double for ALL apps, so upgrading without a seed silently changes a Messaging user's Single buzz into Double - the silent class of regression the review asked about. Enabled state needed no migration: the cards wrote the same app.<pkg>.enabled keys the picker reads (cards' onToggle -> setAppEnabled only, verified on the base tree). The seed runs once at startup, writes ONLY where the pattern key is absent, never overwrites an explicit choice, and is pinned by NotifPatternSeedTest.
|
Thanks for the close read. All four items addressed; pushed as 1 — CHANGELOG hunk: dropped. 2 — Screenshots: out of the tree. 3 — Acknowledged buzz: extracted. 4 — The question (category-card users). Verified on the base tree: the cards were UI grouping over the same key space — While tracing this I found the regression that IS silent, in the direction you pointed: the pattern default. Base code fell back to Gates on the new head: compile green; |
…ate on extras VALUES, not key presence
What
Replaces the curated 9-app notification catalog with live on-device discovery. The Notifications screen gains an App Notifications section (a Choose Apps button opening its own page) that lists every user-installed app that can post notifications — each with its own enable switch, buzz pattern, and test button. Wrist alerts inherit the existing quiet-hours and only-when-worn rules unchanged, and gain a buzz-specificity gate: progress-bar rows and persistent non-dismissable rows never buzz.
Why
The curated catalog covers nine apps. Everything else — BeReal, Slack, Ring, whatever — was reachable only through the "All other apps" catch-all (#168), which buzzes for everything or nothing. Users asked to pick apps one by one.
How
NotifierAppDiscoverymerges two sources: installed apps declaringPOST_NOTIFICATIONS(via a MAIN/LAUNCHER-shaped<queries>entry — noQUERY_ALL_PACKAGES, which is Play-restricted and NOOP ships sideloaded) plus every package the listener has seen post (the Notification Access grant carries their visibility, covering pre-API-33 targets that never declare the permission).FLAG_SYSTEM(OEM agents and bundled services that never notify shouldn't flood the list), the discovered path does not — a preinstalled app that has actually posted a notification (Gmail, Samsung Messages, a carrier app) is one the user demonstrably uses, and hiding it would leave a real notifier unpickable. Posting is the evidence; the flag is not.app.<pkg>.enabled/app.<pkg>.pattern), so the listener gates discovered apps exactly like curated ones — no new preference surface.WristAlertFilters): the per-app mirror path skips progress notifications (download/upload bars, timer countdowns) and persistent non-dismissable rows (FLAG_NO_CLEAR) — app state readouts, not alerts. The Clock alarm/timer path additionally skips progress rows: a running timer no longer buzzes at start, while a genuine alarm ring is a fresh post without progress and keeps its triple buzz (ongoing stays allowed on that path — the whole point of Explore haptic/vibration feedback for incoming calls #1115 — so the persistent gate is deliberately not applied there). Progress is detected from extras values (progress/progressMaxabove zero, orprogressIndeterminate=true) plus theandroid.widget.ProgressBartemplate — never key presence (see Follow-ups).app.<pkg>.enabled, so an opted-in user's enabled set carries over untouched and appears pinned in the picker (no category key space exists to migrate; verified on the base tree: cardonToggle→setAppEnabledonly). What the cards did carry implicitly was their per-category default pattern (Messaging = Single, Email/Calendar = Double, Meetings = Triple), which was never persisted for apps whose pattern was untouched. The picker's package-keyed read defaults to Double for ALL apps — so a one-time startup seed writes each legacy default as an explicitapp.<pkg>.patternONLY where the key is absent, never overwriting an explicit choice, flag-guarded to run once. A Messaging user's Single buzz survives the upgrade; pinned byNotifPatternSeedTest.UI
Scope
Android only. Zero iOS/macOS files touched — the Apple tree is untouched (
git diff --name-only <base>..HEAD | grep -v '^android/'is empty).Tests & gates
NotifierAppDiscoveryTest: 10 tests (filter rule, discovery store, system-package exclusion on the enumeration path, and a regression test that a preinstalled poster like Gmail stays pickable).NotifPatternSeedTest: 5 tests (carried-over Messaging opt-in keeps Single; explicit choices never overwritten; disabled apps get no seeded key; seed runs once and never re-applies; Triple/Double defaults pinned verbatim to the removed category cards).WristAlertFiltersTest: 8 tests on the pure framework-snapshot policy (plain alert is neither progress nor persistent; determinate bar, indeterminate spinner, and ProgressStyle template are filtered; NO_CLEAR is persistent-only; the combined timer row) — including the regression test that the framework's default extras values do NOT filter a plain notification.Tools/i18n_audit.py --ci HEAD: no new hardcoded literals, no new Android locale gaps; all new copy extracted across the 9 gated locales (de/es/fr/it/pl/pt-PT/ru/zh).Tools/doc_comment_lint.py: clean.Refs #168, #1115, #921
Follow-ups since opening
Review pass (#2707 comment 6142632300), item by item:
FLAG_SYSTEMon both discovery paths, which hid OEM-preinstalled apps that actually notify (Gmail, Samsung Messages). The flag filter now applies only to the enumeration path; anything the listener has seen post is offered regardless of the flag. Regression test included.docs/releases/vX.Y.Z.mdbyTools/appchangelog-gen.py, so the hand-written## 12.0.1:heading goes; the prose stays here for whoever writes the notes for the version that carries this.docs/screenshots/Screenshot1-3.pngare removed from the diff — the directory exists nowhere on main, nothing references them, and a picker screenshot archives whatever was installed on the phone it was taken on. They stay in this body hosted on the fork'sassets/pr-2707-screenshotsref (metadata-stripped), not in the merged tree.buzz→buzzAcknowledgedalters what goes over the radio on every mirrored notification, in a PR whose subject is a settings screen, and its justification is the Sweep the Android French for the #884 error classes, with agreement (#884) #921 hypothesis, not a measurement that a without-response write was dropped. Confirmed writes cost a GATT round trip on a strap family with a drain history (android: advance the #836 watermark after the post-backfill re-score #1120/WHOOP 4.0: offload auto-continue (#364/#451) spins empty-offload storms — guard 2a ignores rows #1144/fix(analytics): stop the post-offload re-score flickering daily history to empty (#1196) #1197/fix(ble): gate empty-offload auto-continue on the sensor-record verdict, not a re-read counter (#1146) #1198). The picker lands with the bare write; the acknowledged write will arrive separately with drop evidence attached, so a later drain move has one variable to look at.extras.containsKey("android.progress"), which is a trap: the framework seedsandroid.progress=0,android.progressMax=0andandroid.progressIndeterminate=falseinto the extras of ORDINARY text alerts (device dumps show all three keys on plain notifications), so the gate silenced every buzz. The shipped gate reads VALUES only — indeterminate flag set, progress/progressMax above zero, or the ProgressBar template — with a pinned regression test asserting plain framework defaults are not filtered. On the alarm path this silences timer starts; alarm rings (fresh posts, no progress) keep their triple buzz.Command response: RUN_HAPTIC_PATTERN_MAVERICK → PENDING(2)/FAILURE(0)), including bare writes. No dropped bare write was found, so the evidence bar the acknowledged-write follow-up must clear has not been met — that change stays unshipped. The real measured signal is strap-side pacing:FAILURE(0)answers appear when buzzes arrive faster than ~1s apart (a notification burst floods the pattern player). Pacing/coalescing of mirrored bursts is the candidate follow-up, not write mode.Screenshots
1 — Notifications page: the App Notifications section sits right after Calls, with the full-width Choose Apps button. The delivery note shows the Notification Access grant live.
2 — App Notifications page, mid-scan: the opted-in app (BlueBubbles, pinned above search with its Triple pattern) is visible while the scan is still running — the "Scanning Installed Apps…" placeholder fills the list area below.
3 — App Notifications page, scan complete: pinned pick on top, the discovered notifier apps below with their real launcher icons, each with its own switch.