Research: traceability matrix, Android research findings vs ADR-MOB-001..010¶
Issue: #812 (parent #789; epic #81; relates to the M0 design review #98 and to #807)
Snapshot: YazSes main at 1698395d, inspected 2026-11-06. Issue states checked with gh issue view on the same day (section 6).
Status: Research note, not a decision. ADR-030 freeze unchanged. Evergreen research per the milestone policy (no milestone).
Scope: documentation only. No android/ change, no ADR edited, no APK, no device was used and no device result is claimed. Every "verified" label below means "the ADR text was read at the cited line" or "the #807 note states it from a primary source as summarised by a fetch tool"; none means "observed on a phone".
The only input evidence is the single landed research note, #807 (called "the #807 note"; its S# are numbered sources, C# constraints, Q# questions, T# device tests). Its own caveat applies to everything here: its sources were read as tool summaries, two were truncated.
1. Labels¶
| Label | Meaning in the matrix |
|---|---|
| Supported | The #807 note cites a primary source (S#) consistent with the ADR claim. |
| Contradicted-in-wording | A primary source in the note differs from the ADR's wording; the design intent may still be sound. |
| Unverified | The ADR asserts it; the #807 note found no source and says so ([Unknown]/[Assumption]). |
| No evidence | The #807 note did not examine this decision. This is not a finding of correctness. |
Recommendation vocabulary: No change, Small change to an M1 issue (#87-#92 acceptance text), Amend ADR (PROPOSED) (wording drafted in section 4; nothing applied), Device test first.
2. Matrix¶
ADR citations are file:line under docs/mobile/adr/. Alternatives are what the ADR itself rejects, or, where marked, what the evidence newly suggests.
| # | ADR decision (file:line) | #807 evidence | Label | Alternatives | Backward compatibility | Recommendation |
|---|---|---|---|---|---|---|
| 1 | MOB-003:25, :81-83 and MOB-007:75-76, MOB-004:28-31: a visible IME window makes the app "in use", so hold-to-talk needs no microphone foreground service | Q4: no source states that an IME may record only while its window is shown, nor how capture policy classifies an IME process; S1 lists "current input method" as an FGS-start exemption, which does not prove the capture rule; S4: background app without FGS or foreground gets silence since Android 9. Section 6 item 1 of the #807 note. | Unverified (core premise of M1) | (a) Keep as is and test (T1). (b) Run a short microphone FGS only around a hold, started while the IME is the current input method (S1 exemption). © Detect silence and surface "mic unavailable". None adopted here. | An FGS adds FOREGROUND_SERVICE_MICROPHONE to the :feature:ime path and a notification during holds; MOB-007:44 already budgets the permission for :feature:meeting, so no new permission, but a new module owner. Removing the FGS later is source-compatible. | Device test first (T1), then decide. Proposed ADR note A1 (section 4). Until T1 reports, #89 and #88 must not claim the premise as fact. |
| 2 | MOB-004:57-59 / MOB-007:77-80: Meeting Mode is a user-started microphone FGS from a Quick Settings tile, shortcut or in-app button | C7: type and permission mandatory on target 34, creation from background throws (S2, S1, S7). C8: S1's exemption list as read names bubble, notification, widget, activity tap and current IME; a Quick Settings tile start is not named. | Supported for the in-app button and shortcut path (as far as an activity is visible); Unverified for the tile | Start the FGS only from an activity the tile launches (visible UI first). | No data or API compat issue; a design pre-M3. | Small change to Meeting Mode issue text and #97: the tile path must be tested (T5) and may need to route through an activity. No ADR amendment. |
| 3 | MOB-007:28-30: "Android 15+ applies time limits to several FGS types" | C9: S3/S2 document time limits for dataSync, mediaProcessing, shortService, not microphone. | Contradicted-in-wording (the claim of an applicable limit for the type that matters is not supported by the text read) | None needed; it is a wording issue. #97 remains the empirical check. | Wording only. | Amend ADR (PROPOSED), A2. Keep #97 open (needs devices). |
| 4 | MOB-007:78-80: Meeting Mode "permanent notification" with elapsed time and stop action | C10, S26: FGS starts without POST_NOTIFICATIONS; notification then appears only in the Task Manager, not the drawer. FGS notification display may be delayed 10 s (S14). | Contradicted-in-wording (permanence depends on a runtime grant) | Make the grant part of the Meeting Mode start flow; refuse to start without it, or start with a non-notification indicator. Design choice, not made here. | Wording only; behaviour change is additive. | Amend ADR (PROPOSED), A3, and small change to onboarding #91 (request POST_NOTIFICATIONS before first Meeting Mode, handle denial). |
| 5 | MOB-007:83-84 and #88 acceptance "Mic stolen by another app -> clean stop": capture stops on "another app taking the mic" | C1/C3, S4: on API 29+ the app is silenced, not stopped or errored; AudioRecordingCallback must be registered before capture; pre-29 startRecording errors if the mic is busy. | Contradicted-in-wording (the signal differs by API level and is not an error) | Treat isClientSilenced as the stolen-mic signal on 29+, the start error on <29. | #88 is open; the change is to acceptance text, not shipped behaviour. | Small change to #88 (A4 wording). No ADR amendment strictly needed; MOB-007:83 may be narrowed in the same edit as A2/A3. |
| 6 | MOB-007:39-45 permission table (the manifest is a reviewed artefact) | C7, C10, C20: no POST_NOTIFICATIONS runtime rationale, no foregroundServiceType manifest note, no Play FGS declaration (S24). | Supported (the permissions listed are the right ones); table is incomplete (notes only) | Add a notes column; do not add permissions. | Additive documentation; MOB-007:50 requires the table to change with any manifest PR. | Amend ADR (PROPOSED), A5 (notes only). |
| 7 | MOB-002:44-46: minSdk 26, "target the current stable SDK and keep it current" (and the toml comment that 26 is where IME APIs are "consistent") | Q1, section 4: no read source marks 26 as an IME-API boundary; documented boundaries are audio (28/29), mic UI (31), FGS typing (34). C17/S22: Play requires target 36 for new apps and updates from 2026-08-31 (extension to 2026-11-01); repo targetSdk is 34. No install-share figure was read. | minSdk rationale Unverified; "keep target current" Supported; current target is below the Play bar (irrelevant to GitHub/F-Droid per C17) | Floor 29 or 31 (#807 section 4): unknown cost, no evidence to move. | Raising minSdk drops devices; not recommended on this evidence. A target bump changes FGS/permission behaviour (MOB-009:84-86). | No change to minSdk. Small change: reword the toml comment to drop the uncited claim (a code-owner edit, outside this note); schedule a target-bump test pass before any Play work. |
| 8 | MOB-009:36-39, :84-86: F-Droid-shaped, GitHub APK first, Play later; annual target-SDK obligation | C17 gives the concrete date and level; C20: Play FGS declaration with video, AccessibilityService policy (S24, S23). Distribution trust signals are #810 (not researched). | Supported | Play-first is already rejected (MOB-009:90). | Nothing shipped. | No change to the decision. Note the Play facts in the Play-readiness work when that starts; #810 owns the rest. |
| 9 | MOB-003:26, :30: RecognitionService second; overlay bubble with SYSTEM_ALERT_WINDOW | Q5/C19, S15/S16: on-device recogniser API levels 31/33/34; default impl "likely to stream audio to remote servers"; user-selected default varies by OEM ([Unknown]). C8, S8: at target 35 the overlay exemption requires permission and a visible overlay window. | Supported (levels); OEM picker Unverified; bubble exemption Contradicted-in-wording at target 35+ | None needed. | Bubble is M3 and opt-in; wording only. | Amend ADR (PROPOSED), A6 (bubble clause only). Device test T9 for the picker. |
| 10 | MOB-005:94-97: two JNI bridges; handles behind Closeable; no native call on the main thread; crash takes the IME process | C14/C15: S5 says release large allocations soon after the IME window hides, which pulls against keeping a model hot; largeHeap likely does not govern native allocations ([Assumption]); no per-device model budget in any source. Separate android:process for the engine not researched. | Lifecycle policy Unverified; the Closeable rule is No evidence against | Load on first burst vs keep warm vs separate process (open; needs T7). | Policy choice is internal; no data format affected. | Small change to #92 and #87: record peak RSS and PSS per model, and measure first-burst latency after the process is killed (T7). No ADR amendment until numbers exist. |
| 11 | MOB-006:39-45: model download is a WorkManager job, Wi-Fi only by default, user-initiated | C12/C13: Doze and buckets may defer jobs; bucket criteria are OEM-defined; Android 16 job quotas (S10, S17, S18). | Supported with a caveat | Keep it a foreground, user-visible download (already "nothing downloads before an explicit tap", MOB-006:35-36). | Compatible. | Small change to #90: acceptance should require resume after process death and deferral, with the user-visible progress path. No ADR change. |
| 12 | MOB-007:26 and MOB-003 onboarding duty: honest keyboard privacy explainer; RECORD_AUDIO request | C5/C6, S12: request API needs an Activity, so an IME needs an onboarding activity; two denials are permanent; "only this time" ends with process kill; unused-app auto-reset (target 30+) can revoke the grant. C4: mic toggle yields silent audio, not an error. | Supported (consistent), constraints new to the issues | n/a | Compatible. | Small change to #91 and #89: handle revoked-mid-session, permanent denial, and distinguish "toggle off or silenced" from "quiet room" in the UI wording. |
| 13 | MOB-001 (Android-first, in-repo; Decision at adr-mob-001-android-first-monorepo.md:49) | None | No evidence | n/a | n/a | No change. |
| 14 | MOB-008 (cross-platform contract, adr-mob-008-cross-platform-contract.md:39) | None | No evidence | n/a | n/a | No change. |
| 15 | MOB-010 (Apple wave after Android M2, adr-mob-010-apple-second-wave.md:47) | None | No evidence | n/a | n/a | No change. |
| 16 | 16 KB page size (no ADR line owns it; MOB-005 owns the JNI bridges) | C16, S11: all .so must be 16 KB aligned for targets 35+ on 64-bit; Play block from 2027-02-01 for non-compliant updates; AGP >= 8.5.1 met by repo AGP 8.7.2; NDK unpinned. | Supported; gap, not an ADR contradiction | Pin NDK >= r28 when :native:* land. | None yet; no native build exists (per the #807 note section 1). | Small change to #87 (NDK pin and zipalign -P 16 check, T8). |
Rows 13-15 are placeholders for completeness: the note examined none of them, and the gap itself is a finding.
3. The unverified premise, stated plainly¶
Assumption under test. "Because the IME window is visible while recording, the app is 'in use' for the while-in-use RECORD_AUDIO rule and needs no microphone foreground service for hold-to-talk" (MOB-003:81-83; restated at MOB-003:25, MOB-007:75-76 and, as a constraint, MOB-004:28-31).
What is established. The platform documents that a foreground app, or an app with an FGS, may capture, and that other apps receive silence (S4). The current input method may start FGSs from the background (S1). The InputMethodService reference (S6, partial) says an IME "could have no input area ... but instead listen to audio". What is not established: that an IME process is classified as foreground for capture while its window is shown, that a hidden IME is silenced, and whether this differs by API level or OEM (Q4, Unknown). The note's search for an AOSP rule returned nothing usable.
Why it matters. It is the product's primary path (MOB-004 decision 1). If wrong, hold-to-talk would capture silence on some builds, and the symptom (a quiet buffer) is indistinguishable from a quiet room unless the UI separates them (row 12). No code depends on it yet: :platform:audio capture is "written but never run" (#807 section 1).
Proposed device test (no result exists). Extends #807's T1 into a runnable procedure. Use synthetic or consented own-voice audio only, install nothing that measures through a third-party SDK.
| Step | Do | Record |
|---|---|---|
| 1 | Build a minimal IME whose mic key opens AudioRecord (16 kHz mono PCM16) on key-down and logs RMS per 100 ms until key-up. No FGS. | Device model, SoC, Android version and patch, OEM skin, install source |
| 2 | Hold with the keyboard window shown, in a plain app, a browser field, and a field in a second window (split screen). | RMS non-zero vs zero; AudioRecordingCallback isClientSilenced |
| 3 | Hold, then hide the window mid-hold (back, home, switch IME), keep the key state. | Does audio continue, go silent, or error; time to change |
| 4 | Repeat 2-3 with the mic toggle on and off (C4) and after revoking the permission (C5). | Distinguish silenced vs permission vs toggle |
| 5 | Repeat 2-3 with a short microphone FGS (started while the IME is current) around the hold. | Whether (3) changes; notification visibility with POST_NOTIFICATIONS denied (C10) |
| 6 | API levels: at minimum 26, 29, 31, 34 images (aligns with #674 and #686), then one non-Pixel OEM skin. | Per-cell result table |
Decision rule (proposal). If step 2 and 3 show continuous audio on every tested cell, relabel the premise "Verified on
4. Draft ADR amendments (PROPOSED, not applied)¶
Nothing below edits docs/mobile/adr/. Each is wording a maintainer may adopt in a separate L3 change. None changes scope or ADR-030.
- A1 (MOB-003, MOB-004, MOB-007). Replace the flat assertion with: "Hold-to-talk is expected not to need a microphone foreground service because the IME window is visible. This is unverified (see the 2026-11-06 traceability note); [#89] must not ship on this premise until device test T1 passes on the tested set, and a fallback of a short
microphoneFGS started while YazSes is the current input method is specified." Backward compatible: it only adds a condition. - A2 (MOB-007:28-30). Replace "Android 15+ applies time limits to several FGS types" with "Android 15+ applies time limits to some FGS types; the documentation read names
dataSync,mediaProcessingandshortService, and no limit formicrophonewas found. #97 measures it." - A3 (MOB-007:78-80). Add: "The ongoing notification is visible in the drawer only when
POST_NOTIFICATIONSis granted; the start flow requests it and handles denial." - A4 (MOB-007:83-84, and #88 acceptance, which is an issue edit not an ADR edit). "Another app taking the mic" becomes: "on API 29+ the app is silenced and notified through
AudioRecordingCallback(registered before capture); on API <29startRecordingerrors if the mic is busy. A silent buffer is not by itself an error." - A5 (MOB-007 table at :39-45). Add a Notes column:
POST_NOTIFICATIONSruntime grant;foregroundServiceType="microphone"on the service; Play Console FGS declaration and demo video for a Play listing. - A6 (MOB-003 bubble). Add: "From target 35 the background-start exemption needs the overlay permission and a visible overlay window."
Alternatives to amending: leave the ADRs and track A1-A6 only in the M1 issues. This is cheaper but leaves the ADRs, which contributors treat as binding, stating a premise the project has not verified; the review in #98 is the natural venue to decide.
5. Priorities for epic #81¶
Ranked by cost of being wrong times closeness to the first shipped behaviour. This is a recommendation, not a plan commitment; ordering across contributors is the maintainer's call.
- T1 hidden/visible-IME capture test (row 1). Blocks the confidence of #88 and #89 and decides whether MOB-003/-004/-007 change. Needs one device or emulator image plus a few OEM devices; no project code beyond a spike.
- #88 acceptance rewording (row 5, A4) and #91 onboarding handling (rows 4, 12). Text-only, near-zero cost, prevents building the wrong stolen-mic and permission paths.
- #92 peak-memory and cold-start measurement (row 10, T7). Needed before a model recommendation is made in #90 and before the load policy is chosen.
- #90 job deferral acceptance (row 11) and #87 NDK pin and 16 KB check (row 16). Cheap now, expensive once native builds exist.
- #97 90-minute Meeting Mode spike (rows 2, 3, 4). Device-heavy, and Meeting Mode is later than hold-to-talk. Wording fixes A2-A3 do not need to wait.
- Wording amendments A2-A6 in one batch, after #98 feedback. Defer any minSdk or target change; no evidence argues for either now.
6. Verification record¶
gh issue view <n> --json number,state,title on 2026-11-06, all returned OPEN: #81 (Epic: YazSes for Android), #789 (Android adoption and mobile voice UX), #98 (Design review of the ten mobile ADRs), #807 (Audit Android API level and OEM IME/microphone restrictions), #812 (Map Android research results to M0-M3 ADRs and decision gates), #97 (Spike: 90-minute microphone foreground service on Android 15/16), #88 (:core:audio + :core:vad + :platform:audio), #87, #89, #90, #91, #92, #93, #810, #674, #686. #807 remains open: this note does not close its device-test checklist and #812 stays open until a maintainer accepts or amends.
ADR line citations were read in this worktree at the snapshot above. The #88 acceptance quotes ("Mic stolen by another app -> clean stop, no crash, user told") come from the issue body read on the same date.
Limits. No device, emulator, Gradle build or Android test was run. The #807 sources were summaries, two truncated. Rows 13-15 rest on absence of evidence. Row 7's Play dates are from S22 as summarised, and should be re-read from the primary page before anyone schedules a bump.
Related: #807 note, ADR-030, milestone policy, mobile programme.