Everything this ROM changes on top of a stock Android 17 (Baklava) AOSP build for
Cuttlefish (aosp_cf_x86_64_phone), including the crDroid + LineageOS feature stack being
ported on top of AOSP. This file is maintained by hand as features land.
Legend: ✅ working & verified · 🟡 partial / caveats · 🔧 built but not yet verified on-device · ⛔ not yet implemented / blocked
- lineage-sdk forward-ported to A17 (
lineage-sdk/):org.lineageos.platformframework shared library (installed to/system_ext/framework+ shared-lib permissions XML),.internal,-res,LineageSettingsProvider,LineagePreferenceLib. Stripped the 3 hardware HALs (livedisplay/touch/health) and the SPN telephony lib (dead on Cuttlefish/GSI). A few A16→A17 API-break fixes (LockPatternUtils get/setBoolean, DevicePolicyManagerrequireSecureKeyguard(), 3 removed-constant inlines in the settings DB migrations). ✅ - crDroidSettings merged into the AOSP Settings app (
packages/apps/Settings/crDroidSettings/): compiled intoSettings-core(its 113 sources usecom.android.settings.R+ Settings base classes), linked againstorg.lineageos.platform+LineagePreferenceLib. ✅ - ~155 custom
Settings.System/Secure/Globalkeys added toframeworks/base/core/java/android/provider/Settings.javaas@hide @SuppressLint(...)constants (values taken from crDroid's fork; kept out of the public API surface). ✅ - 4
LineageSettingskeys added tolineage-sdkLineageSettings.java(with validators). ✅ - SystemUI ↔ lineage-sdk link (
packages/SystemUI/Android.bp+ manifest<uses-library>+provides_uses_lib): SystemUI can now readLineageSettings. ✅ - TunerService prefix system (
packages/SystemUI/.../tuner/TunerServiceImpl.java): tunables can observe any settings table via key prefixessystem:/secure:/global:/lineagesystem:/lineagesecure:/lineageglobal:(no prefix = Secure, preserving stock behavior). AddedTunerService.parseInteger(). This is the enabler used by most SystemUI feature backends. ✅ - crDroid framework helpers placed in
frameworks/base/core/java/com/android/internal/util/crdroid/(ThemeUtils, Utils, OmniJawsClient, cutout/CutoutFullscreenController).Utils.restartSystemUI()reimplemented viaActivityManager.forceStopPackage("com.android.systemui"). ✅ - Core-res additions (
core/res/res/values/config.xml+symbols.xml):config_pocketModeSupported,config_notificationsBatteryReallyFullARGB,config_dozePulseProximity,config_dozePulseTilt,config_deviceHaveWakeUpProximity. ✅ AbsSeekBar.updateTouchProgress()hook (core/java/android/widget/AbsSeekBar.java) — identity default, for crDroid's BacklightTimeoutSeekBar. ✅- Product packaging (
device/google/cuttlefish/shared/phone/device_vendor.mk): adds CustomOptions,org.lineageos.platform(+xml),LineageSettingsProvider. ✅
- Homepage entry ("IchthysOS" tile, top of the Personalize section) wired into
top_level_settings_expressive.xml+_expressive_desktop.xml(A17 loads the expressive homepage variants) and registered inSettingsGateway.ENTRY_FRAGMENTS. Opens the full tabbed crDroid UI (Status bar / Quick settings / Lock screen / …). ✅
- Fixed the Lock screen / Buttons / right-hand tab crash (
InflateExceptiononButtonBacklightBrightness). The tabbed UI's ViewPager2 (offscreenPageLimit = 1) preloads the adjacent Buttons tab, whoseButtonBacklightBrightnesspreference readsorg.lineageos.platform.internal.R.*resources. The lineage-sdk resource package (id0x3f,/system_ext/framework/org.lineageos.platform-res.apk) isn't attached to the Settings app's runtime AssetManager, so those reads threwResources$NotFoundExceptionand crashed the tab (and, via preload, the adjacent Lock screen tab). Added resilientDeviceUtils.getLineageInteger/Boolean/ Float(context, resId, default)helpers and routed all 16 lineage-internal-R reads (DeviceUtils, ButtonBacklightBrightness, Buttons, Notifications) through them, falling back to lineage-sdk's own config.xml defaults (correct on Cuttlefish, which has no hardware keys / button backlight / LED). ✅ verified: Lock screen and Buttons tabs open cleanly. - Confirmed the battery-percent toggle works (was reported "broken"): setting
status_bar_show_battery_percent= 1 renders the percentage inside the status-bar battery. It was simply at the default value 0 (hidden); no backend bug. ✅
- ROM name: IchthysOS. Build props (
device/.../device_vendor.mk):ro.ichthys.version/ro.modversion=IchthysOS-1.0, andBUILD_DISPLAY_ID(the build number in Settings > About phone) prefixed withIchthysOS-1.0. The crDroidSettings homepage tile is titled IchthysOS. 🔧 (props need a full image rebuild; the tile needs a Settings rebuild to appear). - Boot animation (
device/.../phone/bootanimation.zip): custom IchthysOS animation, restructured into three parts around the true seamless loop so the fish spins for the entire boot and the IchthysOS logo plays exactly once at the end. Frame-diff analysis found the spin has an exact 29-frame period (frame 30 == frame 1), sodesc.txt=680 680 24/p 0 0 part0(frames 1–29, the seamless spin loop) /c 1 0 part1(frames 30–71, transition out of the spin) /c 1 0 part2(frames 72–100, morph → ICHTHYS → "IchthysOS"). Both closing parts arec(play-to-completion) so they survive the boot-complete signal. ✅ verified via livebootanimpreview. Preview any time:setprop service.bootanim.exit 0; setprop ctl.start bootanim(fish loops) thensetprop service.bootanim.exit 1(plays the spin-down + logo finale).
- 24-hour time is the ROM default (
core/java/android/text/format/DateFormat.java) unless the user explicitly chose 12h. ✅ - Status bar clock shows seconds by default (SystemUI Clock + crDroidSettings pref default). ✅
- Clock customizations (
packages/SystemUI/.../statusbar/policy/Clock.java): seconds, AM/PM style, date (display / style / position / format), period separator (:→.), bold. Added anisStatusBarview attr so date/period apply only to the real status bar clock, not the reused QS-header clock. ✅ - Double-tap status bar to sleep (
.../statusbar/phone/PhoneStatusBarView.java): observes a double-tap on the whole status bar (LineageSettings-gated, default on) without consuming the event, so swipe-to-expand still works. ✅ - Extra status bar padding (start / top / end, live-updating) —
PhoneStatusBarView. ✅ - Battery percent (Compose
UnifiedBatteryviaBatteryRepository/BatteryViewModel): hidden / inside; "next-to-icon" mode maps to "inside" (A17's Compose battery has no next-to layout). Falls back to the AOSPSHOW_BATTERY_PERCENTsetting when unset. ✅🟡 - Battery style (Compose battery): portrait (default) + text-only (verified: text style replaces the icon with the percent number). ✅🟡 — circle / dotted-circle are not implemented (the unified battery is a single rounded-rect path; a real circle needs new drawables). Those values fall back to portrait.
- Notification count badge on status bar notification icons —
StatusBarIconView.java. 🔧 (applies after icons are recreated; only for apps that still setNotification.number). - Colored status bar icons (app/notification color instead of monochrome) —
StatusBarIconView.java. 🔧 (applies after icons are recreated). - Clock position (left / center / right) via
status_bar_clock— ✅ verified: all three positions move the status-bar clock correctly (added center + rightClockviews tostatus_bar.xml, wired inStatusBarRoot.setUpClockPositions). - Battery bar (
statusbar/BatteryBarView.java): a thin, full-width bar along the bottom edge of the status bar whose length tracks the battery level. Added toPhoneStatusBarView(a FrameLayout) inStatusBarRoot.addCrDroidStatusBarViews, clear of the Compose start/end-side overlays. Backs all 10statusbar_battery_bar*settings (enable, thickness, style regular/center-mirrored/reversed, color blend + reverse, normal/low/charging colors, charging-color toggle, animate). Self-observes via TunerService (system:) + an ACTION_BATTERY_CHANGED receiver. ✅ verified: renders full-width along the status-bar bottom edge, width tracks the level, charging color applied. Key finding: the A17 status bar is a realPhoneStatusBarView(FrameLayout) hosted via ComposeAndroidView— only the start/end icon areas get Compose overlays — so a full-width bottom-edge bar renders fine. This unblocks the "new view" status-bar category previously thought blocked.
- Lock screen (
crdroid_settings_lockscreen): double-tap-to-sleep, battery info in the keyguard indication text, power menu on a secure lock screen (gated inPhoneWindowManager), and a fingerprint/face unlock ripple toggle. 🔧 built (SystemUI + services), needs the image to run. - Status bar clock position (left / center / right) via
status_bar_clock— added center + right clock views. 🔧 - Global "Disable all vibration" (IchthysOS): a master toggle under Sound settings that drops
every vibration (haptics, ringtone, notification, alarm, system) at
VibrationSettingsin system_server. 🔧
- Selectable recents implementation (
recents/RecentsModule.java): arecents_typeSettings.System key chooses the recents UI — 0 = Stock (Launcher overview), 1 = Classic (the prior session's revived pre-Quickstep vertical task-list recents,LegacyRecentsActivity). Read once at SystemUI start; changing it needs a SystemUI restart. 🔧 Slim Recents (value 2) is reserved but not implemented — no working modern (A15/16) source exists to port (AICP/crDroid dropped the SystemUI impl in the Compose rewrites; only vestigial settings remain in AICPExtras). crDroidSettings UI toggle still TODO.
- Android 8.1-style collapsed QS (
qs/panels/.../QuickQuickSettings.kt+ ViewModel): single row of icon-only circular tiles. ✅ - QS brightness slider (
brightness/ui/compose/BrightnessSlider.kt): thinner, shows a percentage number, much smaller vertical footprint so the tiles sit higher. ✅ - QS layout spacing tightened (
res/values/shade_dimens.xml,dimens.xmlqs_panel_padding_top80dp→16dp,overlay_qs_layout_vertical_padding16dp→4dp). ✅
- Horizontal (Android 8.1-style) volume slider: rectangular track, live volume step number
replacing the settings/VU button, thinner, ringer/mute drawer removed, pitch-black
background with an accent border, centered, white slider-bounds outline. Backed by a live
volume-level flow in
VolumeDialogViewModel. ✅ - 3-digit volume number support. ✅
- Pitch-black mode (
theme/ThemeOverlayController.java): the Monet engine's dark surface/background roles and the dark end of the neutral tonal palettes are forced to pure black instead of a slightly accent-tinted dark shade (gated bycustom_pitch_black). ✅
- QS quick/smart pulldown — ⛔ A17 uses the new Compose scene shade (
scene_containerenabled); crDroid's pulldown lives in the legacy shade which isn't instantiated. Decision: stay on the scene framework and re-implement (smart pulldown is state-based and doable; quick-pulldown-by-edge needs custom scene gesture work). Not reverting to legacy shade. - Status bar: wifi-standard indicator, bluetooth battery — ⛔ blocked on A17's Compose status-bar pipeline (shared viewmodels / missing controller APIs).
- Status bar: logo, network traffic, dynamic bar, clock chip — ⛔ / ⏸️ not yet rendering (new-view features; logo + network traffic are added to the bar but covered by A17's Compose start-side overlay — network traffic is deferred to the final batch per user). Clock left/center/right position ✅ and the battery bar 🔧 are now done (see §5).
- Most crDroidSettings toggles outside the areas above — ⛔ the setting persists but no SystemUI/framework backend reads it yet (stage-4 work in progress).
Last updated: 2026-07-13. Maintained alongside the port; sections move from 🔧 to ✅ as features are verified on-device.