Skip to content

Repository files navigation

Marine Command OS

Android platform-architecture simulation for marine bridge electronics — a reusable SDK, a privileged Binder/AIDL platform service, and product surfaces (launcher, chartplotter, sonar, command deck, settings, device management, OTA).

Built to demonstrate how launcher / settings / device / data / OTA can share one coherent platform boundary (the same separation you’d enforce on a real MFD running an AOSP-derived image).

Honest scope: This is an Android Studio multi-module app simulation, not a full AOSP fork or flashed system.img. The architecture mirrors a real platform service + SDK + product apps stack; hardware and UpdateEngine are simulated.


Why this project exists

Marine / automotive / CE platform teams need engineers who can:

  • Own product surfaces (launcher, settings, device UI) without leaking HAL details into apps
  • Define a stable SDK contract that multiple product lines can reuse
  • Run privileged work in a platform service over Binder/AIDL
  • Reason about OTA state machines, alerts, and process boundaries

Marine Command OS is a concrete, runnable demo of that stack.


Architecture at a glance

flowchart TB
    subgraph Product["Product layer — :launcher"]
        HOME[HOME / MainActivity]
        CHART[Chartplotter]
        SONAR[Sonar]
        DECK[Command Deck]
        SETTINGS[Settings]
        DEVICES[Device Management]
        OTAUI[Firmware and OTA]
    end

    subgraph SDK[":sdk — stable contract"]
        MM[MarineManager facade]
        AIDL[IMarineDataService / IMarineDataListener]
        VS[VesselState]
    end

    subgraph Platform[":platform-service — privileged process"]
        SVC[MarinePlatformService]
        OTA[OtaStateMachine]
        SIM[Simulated Marine HAL]
    end

    HOME --> MM
    CHART --> MM
    SONAR --> MM
    DECK --> MM
    SETTINGS --> MM
    DEVICES --> MM
    OTAUI --> MM

    MM --> AIDL
    AIDL -->|Binder + signature permission| SVC
    SVC --> OTA
    SVC --> SIM
    SIM -->|VesselState callbacks| AIDL
Loading

Design rule

Product surfaces talk only through MarineManager.
They never import service internals or touch the simulated HAL directly.

Layer Module Responsibility
Product UI :launcher (com.zhk.marine.launcher) HOME launcher + Chartplotter, Sonar, Command Deck, Settings, Device Management, OTA screens
SDK :sdk (library) AIDL contracts, VesselState, MarineManager facade
Platform :platform-service (com.zhk.marine.platformservice) Privileged service, telemetry simulation, OTA state machine

Signature permission: com.zhk.marine.permission.BIND_MARINE_SERVICE


Runtime flow (Command Deck example)

sequenceDiagram
    participant UI as CommandDeckActivity
    participant SDK as MarineManager
    participant SVC as MarinePlatformService
    participant HAL as Simulated HAL loop

    UI->>SDK: bind()
    SDK->>SVC: bindService (BIND_AUTO_CREATE)
    SVC-->>SDK: onServiceConnected (IBinder)
    SDK->>SVC: registerListener(IMarineDataListener)
    loop every 1.5s
        HAL->>SVC: update latestVesselState
        SVC-->>SDK: onStateChanged(VesselState)
        SDK-->>UI: Flow emission
        UI->>UI: render gauges / alert if temp > 220°F
    end
    UI->>SDK: unbind()
Loading

Product surfaces

Surface What it shows
HOME Pictorial tiles, platform online status, live SOG / HDG / depth snapshot
Chartplotter Demo chart canvas, fishing spots, waypoints, AIS targets, layer toggles
Sonar Fishfinder water-column view, live depth from platform, frequency / range controls
Command Deck 8-gauge instrument grid via AIDL callbacks; over-temp alert banner
Settings Vessel profile, units, night / keep-awake, NMEA & spot-sync demo prefs, alerts
Device Management Connected-device inventory, diagnostics, entry to Firmware & OTA
Firmware & OTA Device health + OTA progress UI

OTA state machine (demo)

AVAILABLE → DOWNLOADING → VERIFYING → READY → INSTALLING → REBOOT_REQUIRED

Same vocabulary you’d use when talking about staged updates / health checks / rollback on a real UpdateEngine path.


This project vs AOSP

Marine Command OS Full AOSP platform
Goal Prove product↔platform boundary quickly Build / flash entire Android OS image
Build Gradle (Android Studio) repo + Soong/Make (lunch / m)
Runtime App process(es) on phone / emulator system_server + system/vendor partitions
Trust model Signature permission (simulates platform trust) priv-app, SELinux, signature|privileged
Hardware Simulated telemetry + OTA machine HALs (AIDL/HIDL) + kernel drivers
Updates In-process OTA state machine demo UpdateEngine, A/B slots, recovery

Mapping to a real MFD image: product UIs → packages/apps (or vendor apps); SDK → framework stubs / client lib; service → SystemService or privileged app; sim HAL → NMEA 2000 / CAN / sonar HALs.


Project structure

MarineCommandOS/
├── sdk/                  # AIDL + MarineManager + VesselState
├── platform-service/     # Privileged Binder service + OTA + sim telemetry
├── launcher/             # All product surfaces (single demo APK)
├── gradle/
├── build.gradle.kts
├── settings.gradle.kts
└── README.md

Requirements

  • Android Studio Ladybug+ (or equivalent) / JDK 17
  • Android SDK 35
  • Device or emulator API 26+
  • Prefer a dedicated test phone if you set Marine Command as the default HOME launcher

Build

./gradlew :sdk:assembleDebug \
  :platform-service:assembleDebug \
  :launcher:assembleDebug

Windows:

.\gradlew :sdk:assembleDebug :platform-service:assembleDebug :launcher:assembleDebug

Install & run

.\gradlew :platform-service:installDebug :launcher:installDebug

Open Marine Command OS from the app drawer.

Optional: use as HOME launcher (test device only)

adb shell cmd package set-home-activity com.zhk.marine.launcher/.MainActivity

Then press Home.

Restore stock launcher (Pixel example):

adb shell cmd role add-role-holder android.app.role.HOME com.google.android.apps.nexuslauncher

On Samsung / other OEMs, use Settings → Apps → Default apps → Home app.

Do not leave this as Home on a daily-driver phone unless you intend to.


Demo script (2–3 minutes)

  1. HOME shows ONLINE and live snapshot once the platform service binds
  2. Command Deck — gauges update; wait for engine-temp alert (> 220°F)
  3. Chartplotter — spots / waypoints / AIS; toggle layers
  4. Sonar — water column + live depth
  5. Settings — flip units / connectivity toggles
  6. Device Management → Firmware & OTA — tap Check for Update and walk the state machine

Tech notes

  • UI: Material Views + ViewBinding (Compose avoided for Windows classpath reliability on this machine)
  • IPC: AIDL + RemoteCallbackList for multi-listener fan-out
  • Async: Kotlin coroutines + Flow from MarineManager.stateUpdates()
  • Settings persistence: DataStore Preferences (demo shortcut; production would route config through the platform service)
  • Kotlin / AIDL caveat: do not name service fields currentState / otaState — they collide with generated getters and recurse

Roadmap (intentional next steps)

  • AIDL-backed FishingSpotsManager (spots versioned in the platform layer — Navico-style phone↔MFD sync)
  • Real NMEA 2000 / CAN HAL behind the same AIDL
  • SELinux / priv-app packaging on an AOSP derivative
  • Wire OTA demo vocabulary to UpdateEngine on a device image

License

Personal / portfolio project. Add a license of your choice before publishing if you want redistribution terms (e.g. MIT / Apache-2.0).

About

Android platform simulation for marine bridge electronics: SDK + Binder/AIDL service + launcher/chart/sonar/OTA product surfaces

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages