# Meatbag Research: SDUI Inflation, Wear OS Haptics, and Server Push This document summarizes architectural research for the Meatbag platform, focusing on performance, latency, and platform-specific haptic patterns. --- ## 1. Server-Driven UI (SDUI) in Compose Multiplatform ### The Reflection-Free Pattern To meet performance constraints and avoid runtime performance degradation on lightweight clients (such as Wear OS watches), Meatbag implements a strictly typed, reflection-free Component Registry. ```kotlin @Composable fun ComponentRegistry(primitive: UiPrimitive, onAction: (ApprovalResponse) -> Unit) { when (primitive) { is ApprovalRequest -> ApprovalRequestCard(primitive, onAction) is ActionList -> ActionListContainer(primitive, onAction) is TextInput -> TextInputField(primitive, onAction) } } ``` * **Advantage**: Compile-time safety. Polymorphic serialization (via `kotlinx.serialization` with custom class discriminators like `"type"`) ensures payloads map directly to Kotlin data types without dynamic inspection. * **State Management**: Adheres to Unidirectional Data Flow (UDF). Primitives are read-only configuration blueprints; interactive widgets emit state updates upward through explicit event callbacks (`onAction`), keeping clients entirely stateless. --- ## 2. Wear OS Haptic Feedback APIs To minimize human response times, we utilize precise physical notifications based on the resolved `AttentionTier`. ### Android / Wear OS API Mapping For triggering haptics on physical Wear OS smartwatches, the system integrates with Android's hardware `Vibrator` API. #### 1. Predefined Effects (Android SDK 29+) Modern Wear OS devices support the `VibrationEffect` API, which yields crisp, hardware-optimized clicks rather than fuzzy motor rumbling. * **`AttentionTier.SILENT_HAPTIC`**: Double short pulses to signal prompt urgency without making sound. ```kotlin val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator val effect = VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1.0f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1.0f, 150) // 150ms delay .compose() vibrator.vibrate(effect) ``` * **`AttentionTier.BACKGROUND_NOTIFICATION`**: A light tick effect. ```kotlin vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) ``` * **`AttentionTier.OVERRIDE_SCREEN`**: Repetitive pulsing alert composition. ```kotlin val timings = longArrayOf(0, 200, 100, 200, 100, 500) // delay, vibe, pause, vibe... val amplitudes = intArrayOf(0, 255, 0, 255, 0, 255) vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, -1)) ``` #### 2. Legacy Fallbacks (Android SDK < 29) * For older Wear OS versions, fallback to deprecated pattern arrays: ```kotlin vibrator.vibrate(longArrayOf(0, 80, 100, 80), -1) ``` --- ## 3. Server Push Architecture: WebSockets vs. SSE Smartwatches are subject to battery constraints and intermittent connectivity. The push transport layer must be responsive yet lightweight. | Feature | WebSockets | Server-Sent Events (SSE) | | :--- | :--- | :--- | | **Protocol** | Bi-directional, custom framing | Uni-directional (Server -> Client), HTTP/1.1 or HTTP/2 | | **Connection Overhead** | Low (post-handshake) | Extremely low (standard HTTP connection) | | **Battery Impact** | Higher (constant connection maintenance) | Lower (leverages HTTP client connection pooling) | | **Firewall Traversal** | Can be blocked by strict proxy rules | Standard HTTP, easily passes through proxies | | **Meatbag MVP Selection** | **WebSockets** (Allows immediate client confirmation frames and bi-directional pings) | **Candidate for mobile clients** (Fallback for phone targets via standard APNS / FCM) | ### Recommended Hybrid Strategy 1. **Wear OS Smartwatches**: Utilize persistent WebSockets with optimized ping-pong intervals (e.g. 30 seconds) when the app is active in the foreground. 2. **Mobile Phones (iOS & Android)**: Fall back to native push notification systems (FCM/APNS) to wake up the client, which then opens a short-lived WebSocket or POST connection to render the SDUI primitive.