8.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Mosis is a virtual smartphone OS for VR games and applications. It provides a phone-like device that users can interact with inside VR environments, with real smartphone functionality.
Project Components
| Component | Location | Purpose |
|---|---|---|
| Android Service | src/main/ |
Native service running RmlUi renderer |
| Desktop Designer | designer/ |
UI development with hot-reload |
| Designer Tests | designer-test/ |
Automated UI testing framework |
| UI Assets | src/main/assets/ |
Shared RML/RCSS/Lua assets |
Build Commands
Android (Gradle)
# Build entire project
./gradlew build
# Build debug APK
./gradlew assembleDebug
# Build release APK
./gradlew assembleRelease
# Clean build outputs
./gradlew clean
# Build with verbose output
./gradlew build --info --stacktrace
# Run lint checks
./gradlew lint
# Run unit tests
./gradlew test
# Run connected device tests
./gradlew connectedAndroidTest
Desktop Designer (CMake)
# Configure (from designer/ folder)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake
# Build
cmake --build build --config Debug
# Run with hot-reload
./build/Debug/mosis-designer.exe ../src/main/assets/apps/home/home.rml
# Run with logging and hierarchy dump
./build/Debug/mosis-designer.exe ../src/main/assets/apps/home/home.rml --log output.log --hierarchy hierarchy.json
Designer Tests (CMake)
# Configure (from designer-test/ folder)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake
# Build
cmake --build build --config Debug
# Run tests
./build/Debug/designer-test.exe
Environment Requirements
Required environment variables:
ANDROID_HOME- Android SDK pathANDROID_NDK_HOME- Android NDK path (version 29.0.14206865)VCPKG_ROOT- vcpkg package manager root
Architecture Overview
MosisService is an Android application combining Kotlin UI with native C++ libraries for UI rendering via Android's Binder IPC system.
Two Native Libraries
mosis-service (libmosis-service.so):
- Main Android Binder service implementation
- Implements
IMosisService.aidlinterface for touch events and initialization - Contains the Kernel rendering engine with RmlUi integration
- Links against RmlUi for HTML/CSS-like UI rendering
mosis-test (libmosis-test.so):
- Test/rendering client implementation
- Implements
IMosisListener.aidlfor receiving callbacks - OpenGL ES 2.0 rendering pipeline using GLAD
IPC Flow
Kotlin NativeService → JNI → mosis-service (IMosisService)
↓
IMosisListener callbacks
↓
mosis-test (rendering client)
Key Interfaces (AIDL)
IMosisService: initOS(), onTouchDown(), onTouchMove(), onTouchUp()
IMosisListener (oneway/async): onServiceInitialized(), onBufferAvailable(), onFrameAvailable()
Native Code Structure (src/main/cpp/)
kernel.cpp- Core rendering engine, RmlUi integration, event processingmosis-service.cpp- Binder service implementation, JNI entry pointsmosis-test.cpp- Test client implementationegl_context.cpp- OpenGL ES context managementrender_target.cpp- Framebuffer and buffer managementRmlUi_Renderer_GL3.cpp- RmlUi OpenGL renderer backendassets_manager.cpp- Android AssetManager integration
Code Style
- C++23 standard with modern features (std::span, std::format)
- PascalCase for classes/functions, camelCase for variables
- RAII principles with smart pointers
- Kotlin code follows Android conventions
Dependencies
- vcpkg manages native dependencies (RmlUi, GLFW, Freetype, Lua, libpng, nlohmann-json)
- CMake build system with vcpkg toolchain integration
- Android target architecture: arm64-v8a only
- Desktop target: Windows x64 (MSVC)
Desktop Designer
The desktop designer (designer/) provides rapid UI development with:
- Hot-reload: Automatically reloads when RML/RCSS/Lua files change
- UI Hierarchy Dumping: Exports element tree to JSON for inspection
- Screenshot Capture: PNG export via F12 key
- Logging: Detailed output for debugging navigation and events
Key Files
| File | Purpose |
|---|---|
designer/src/main.cpp |
Main entry point, GLFW window, event loop |
designer/src/desktop_kernel.cpp |
RmlUi context management, rendering |
designer/src/testing/ui_inspector.cpp |
UI hierarchy JSON export |
designer/src/testing/visual_capture.cpp |
PNG screenshot capture |
Command Line Options
--log <path> Write logs to file
--hierarchy <path> Dump UI hierarchy JSON each frame
--dump Single-shot dump mode (screenshot + hierarchy)
Automated Testing Framework
The designer-test (designer-test/) provides automated UI testing:
Test Architecture
- WindowController: Finds designer window, sends mouse/keyboard events via Windows SendInput API
- HierarchyReader: Parses UI hierarchy JSON to find elements by ID/class
- LogParser: Monitors log file for navigation events
- TestRunner: Orchestrates test execution, reports results
Writing Tests
// Find element by ID and click it
bool ClickById(TestContext& ctx, const std::string& id) {
ctx.hierarchy.Reload();
auto element = ctx.hierarchy.FindById(id);
if (!element) return false;
int x = element->bounds.centerX();
int y = element->bounds.centerY();
ScaleToPhysical(ctx, x, y); // Convert logical to physical coords
ctx.window.SendClick(x, y);
return true;
}
// Test example
bool TestNavigateToDialer(TestContext& ctx) {
GoHome(ctx);
ctx.log.Clear();
if (!ClickById(ctx, "dock-phone")) return false;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
ctx.log.Reload();
return ctx.log.Contains("Loaded screen: apps/dialer/dialer.rml");
}
Test Output
Tests produce JSON results at test_results.json:
{
"name": "Mosis Designer UI Tests",
"summary": {"passed": 5, "failed": 0, "total": 5},
"tests": [
{"name": "Navigate to Dialer", "status": "passed", "duration_ms": 3500}
]
}
UI Assets Structure
All UI assets are in src/main/assets/:
assets/
├── apps/ # System apps (RML documents)
│ ├── home/home.rml # Home screen launcher
│ ├── dialer/dialer.rml # Phone dialer
│ ├── messages/ # Messages app
│ ├── contacts/ # Contacts app
│ ├── settings/ # Settings app
│ └── browser/ # Web browser
├── ui/ # Shared stylesheets
│ ├── html.rcss # Base HTML element styles
│ ├── theme.rcss # Design tokens (colors, typography)
│ └── components.rcss # Reusable UI components
├── scripts/ # Lua scripts
│ └── navigation.lua # Navigation system
├── icons/ # TGA icon files (24x24, 32x32)
└── fonts/ # TTF fonts (LatoLatin, Roboto)
Navigation System
Navigation is handled by scripts/navigation.lua:
-- Navigate to a screen
navigateTo('dialer') -- Push to history, animate forward
-- Go back
goBack() -- Pop from history, animate back
-- Go home
goHome() -- Clear history, return to home
Element IDs for Testing
Key elements have IDs for automated testing:
| ID | Location | Purpose |
|---|---|---|
dock-phone |
home.rml | Phone dock icon |
dock-messages |
home.rml | Messages dock icon |
dock-contacts |
home.rml | Contacts dock icon |
dock-browser |
home.rml | Browser dock icon |
app-settings |
home.rml | Settings app icon |
CSS Classes for Navigation
Back buttons use app-bar-nav class for automated GoHome:
<div class="app-bar-nav btn-icon" onclick="goBack()">
<img src="../../icons/back.tga"/>
</div>