Skip to content

v1.22 (versionCode 28): production hardening, flavor separation, CI - #7

Merged
wenpeishao merged 9 commits into
mainfrom
omi-glass-ble
Aug 6, 2026
Merged

wenpeishao merged 9 commits into
mainfrom
omi-glass-ble

Conversation

@wenpeishao

Copy link
Copy Markdown
Owner

Release candidate for Play v1.22 (versionCode 28). The standard (production) flavor contains NO research features.

PRODUCTION CHANGES
TLS certificate pinning for mindpulse.ssc.wisc.edu. Enrollment token and key now encrypted at rest (AndroidKeyStore AES-256-GCM) with transparent migration for existing installs. Devicestate heartbeat independent of location permission (WorkManager, 30-min throttle). New health alerts: capture-stall detection plus upload-backlog / low-storage participant notifications. Legacy Encryptor.encryptFile no longer silently destroys recordings. Five-tap DevTools entry gated out of production release builds. Java 17, zero lint errors, 26 unit tests, GitHub Actions CI on every push.

RESEARCH STACK (mindpulseDev flavor only, not in the Play APK)
OMI Glass BLE photo pipeline and on-device VLM/OCR (llama.cpp as pinned submodule). Native build gated by flavor; production APK ships zero native libraries (verified: 20MB, no .so).

RELEASE CHECKLIST

  1. CI green on this PR
    1. bundleStandardRelease with signing.properties
    1. Internal testing track first: verify v1.21 to v1.22 upgrade keeps registration (SecureStore migration)
    1. Promote to production

- Pin TLS certificates for mindpulse.ssc.wisc.edu (InCommon/USERTrust CAs,
  fail-open 2027-07-08) in network_security_config
- Add SecureStore: enrollment token moves from plaintext SharedPreferences
  to AndroidKeyStore-backed AES-256-GCM, with legacy migration and tests
- Sweep crash-orphaned plaintext temp files (Logger.sweepStaleTempFiles)
- Expand DeviceStateCollector battery/runtime diagnostics
- Make legacy Encryptor.encryptFile throw instead of silently no-op:
  callers delete the plaintext source on "success", so a no-op destroyed
  video recordings while logging success
- Add 100k-file upload backlog stress-test scripts and runbook
…seDev

Research features live only in the mindpulseDev flavor; the production
standard flavor gets no-op stubs, no BLE permissions, and no native code.

Flavor separation:
- GlassBleService/GlassPhotoAssembler/VlmBridge/VlmBenchmark/OcrProcessor/
  BehaviorContext moved to src/mindpulseDev; GlassesFeature facade +
  VlmBenchmark stub in src/standard
- BLE permissions and service declaration in mindpulseDev manifest overlay
- Native build gated by -DVLM_ENABLED=ON (dev flavor only); standard builds
  a placeholder excluded from packaging, restoring all-ABI production APKs
  with zero .so files; llama.cpp vendored as a pinned git submodule
- Five-tap DevTools entry gated to debug builds / mindpulseDev

Reliability and privacy fixes baked in:
- GlassBleService: scan filter + balanced mode + exponential backoff
  (results now arrive with screen off), connect-fallback recovers from
  remembered-MAC changes, BT adapter state receiver, GATT status checks
  (a failed CCCD write no longer starts glasses capture), assembler reset
  on reconnect + 2MB cap (no cross-connection JPEG merging), stop-capture
  write grace before close, upload I/O off the BLE binder thread, removed
  the indefinite wake lock, fine-location gate on API 29-30
- VLM: OCR posted to worker thread (was silently returning "" on the
  accessibility path), native mutex + double-load guard (was leaking
  ~700MB per reload), n_batch follows n_ctx (prompts >512 tokens failed),
  UTF-8-safe JNI string returns, loadLibrary guard, -march i8mm removed
  (SIGILL on armv8.2 cores), DevTools listener leak fixed
- Screen-derived text (VLM narrative/captions) and BLE MAC no longer
  written to logcat, which is uploaded as diagnostics
- Ignore model weights (models/, *.gguf), decrypted participant data
  (recentlog/, Screenshot_*.png), local dev prefs, and scratch notes
- Stop tracking .claude/settings.local.json (machine-local, contains
  local paths)
- Register llama.cpp submodule VCS root in IDE config
… alerts

- Enrollment key moves from plaintext SharedPreferences to SecureStore
  (AndroidKeyStore AES-256-GCM) at every read/write site, with the same
  lazy migration + fail-open pattern already used for enrollment_token,
  so existing registered participants migrate transparently
- Devicestate heartbeat now also runs from AutoUploadWorker (30-min
  throttle, deduped against LocationService's 10-min flush), so the
  server-side alive-vs-broken signal flows even for participants who
  declined location permission
- HealthChecker gains a capture-stall alert (consecutive screenshot
  failures while unlocked — overnight non-use cannot trip it) and a
  participant-facing upload-backlog / low-storage alert
- Daily warning into uploaded diagnostics starting a month before the
  TLS pin-set fail-open date (2027-07-08)
Lint (12 errors -> 0):
- New A11yState holder: status flags and API-safe static helpers moved out
  of the @RequiresApi(R) AccessibilityCaptureService, clearing 10 spurious
  NewApi errors at API-29-reachable call sites
- RegisterActivity: deprecated empty onBackPressed() override replaced with
  an OnBackPressedCallback (back stays disabled during registration)
- standard fragment_mindpulse.xml: android:tint -> app:tint

Tests (26 executions, 0 failures; Robolectric + JUnit):
- GlassPhotoAssemblerTest: BLE frame-reassembly state machine (chunking,
  orientation framing, frame gaps, mid-stream joins, reset isolation,
  2MB cap, JPEG validation)
- EncryptorTest: full server-side round-trip of AES-GCM + RSA-OAEP wrap,
  per-file key/nonce uniqueness, legacy encryptFile throws
- LoggerQueueTest: .enc/.meta pair contract, provenance fields, no
  plaintext temp left behind, refuses to queue without the server key
Runs on every push/PR. Skips the native llama.cpp build (dev-flavor Java
compile doesn't trigger CMake; standard never needs the submodule), so a
plain ubuntu runner with JDK 17 covers everything. Lint and test reports
are uploaded as artifacts.
Windows checkouts commit gradlew with mode 100644; the Linux CI runner
then fails with exit 126 (permission denied).
@wenpeishao
wenpeishao merged commit 284be48 into main Aug 6, 2026
0 of 2 checks passed
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.

1 participant