You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add a small Android test app to capture and analyze physical media/volume key delivery behavior for FiiO JM21 (Android 13) devices.
Provide multiple capture paths (MediaSessionService, BroadcastReceiver, and Activity.dispatchKeyEvent) and record environmental context to help reproduce delivery differences when screen/lock/app state changes.
Description
Introduce a new Android application module implementing a foreground MediaSessionService (KeyLoggerService) that plays a silent WAV in loop to keep the media session active and captures media key events via onMediaButtonEvent.
Add BroadcastReceiver (MediaButtonEventReceiver) and Activity-level capture (MainActivity.dispatchKeyEvent) so events from different delivery paths are recorded, and create DeviceStateProvider to snapshot environment state.
Add in-memory logging with KeyEventLogRepository, domain models in KeyEventModels, CSV export (exportToCsv), and a Compose UI in MainActivity to control service/logging and inspect/save logs; include MP3 open/play/seek helpers for manual tests.
Add project metadata: AndroidManifest.xml, Gradle config (build.gradle.kts, app/build.gradle.kts, settings.gradle.kts, gradle.properties), README.md, and detailed docs/TEST_PROCEDURE.md for manual test instructions.
Testing
No automated tests or unit/instrumentation tests were added or executed as part of this change.
downTimestamps.remove(event.keyCode)?.let { now - it }
Track hold timing by source/device, not only keycode
downTimestamps is keyed only by event.keyCode, but this app intentionally logs the same physical press via Activity, BroadcastReceiver, and MediaSession paths. When multiple paths record ACTION_DOWN for one key, the first ACTION_UP removes the shared timestamp and subsequent ACTION_UP entries from other paths get holdDurationMs as null (or an incorrect value), which corrupts per-path hold-duration analysis. Use a composite key (e.g., source + deviceId + keyCode) or derive duration from each event’s downTime/eventTime to keep measurements independent.
The media-button receiver is exported and onReceive accepts any ACTION_MEDIA_BUTTON intent payload, then logs it as a key event. That lets any third-party app send an explicit broadcast with crafted EXTRA_KEY_EVENT values, polluting the experiment logs (and triggering service starts) without real hardware input. Restrict this receiver to trusted callers by setting it non-exported or guarding it with an appropriate permission/caller check.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
BroadcastReceiver, andActivity.dispatchKeyEvent) and record environmental context to help reproduce delivery differences when screen/lock/app state changes.Description
MediaSessionService(KeyLoggerService) that plays a silent WAV in loop to keep the media session active and captures media key events viaonMediaButtonEvent.BroadcastReceiver(MediaButtonEventReceiver) andActivity-level capture (MainActivity.dispatchKeyEvent) so events from different delivery paths are recorded, and createDeviceStateProviderto snapshot environment state.KeyEventLogRepository, domain models inKeyEventModels, CSV export (exportToCsv), and a Compose UI inMainActivityto control service/logging and inspect/save logs; include MP3 open/play/seek helpers for manual tests.AndroidManifest.xml, Gradle config (build.gradle.kts,app/build.gradle.kts,settings.gradle.kts,gradle.properties),README.md, and detaileddocs/TEST_PROCEDURE.mdfor manual test instructions.Testing
Codex Task