Skip to content

feat: handheld auto-configuration for plug-and-play gaming#672

Closed
gigachadmma69 wants to merge 1 commit intoutkarshdalal:masterfrom
gigachadmma69:feat/handheld-auto-configuration
Closed

feat: handheld auto-configuration for plug-and-play gaming#672
gigachadmma69 wants to merge 1 commit intoutkarshdalal:masterfrom
gigachadmma69:feat/handheld-auto-configuration

Conversation

@gigachadmma69
Copy link

@gigachadmma69 gigachadmma69 commented Feb 27, 2026

Summary

  • Replaces the 3-branch GPU if/else in setContainerDefaults() with a 5-tier device detection system that auto-configures optimal Wine/emulation settings
  • Detects device hardware via Build.SOC_MODEL (API 31+) with GPU renderer fallback, covering Snapdragon 8 Elite through 855 and non-Adreno devices
  • Identifies known gaming handhelds (AYN Odin, AYANEO Pocket, Retroid Pocket, GPD XP) by manufacturer/model

Device Tiers

Tier Devices Key Settings
FLAGSHIP_ELITE SD 8 Elite, 8 Gen 3, G3x Gen 3 Turnip Gen8, DXVK 2.4.1, FEXCore PERFORMANCE, MultiBlock on, 4096MB VRAM
FLAGSHIP SD 8 Gen 2, 8 Gen 1, G3x Gen 2 Turnip 26.0, DXVK 2.4.1, FEXCore INTERMEDIATE, MultiBlock on, 3072MB
HIGH SD 7xx, 888, 870 Turnip 26.0, DXVK auto (sarek for 6xx/710-732), FEXCore INTERMEDIATE
MID SD 865, Adreno 6xx Turnip 26.0, DXVK sarek, FEXCore COMPATIBILITY, 960x540
LOW Non-Adreno (Mali, etc.) System driver, async DXVK, Box64 STABILITY, 960x540

How It Works

  1. HandheldProfileManager.detectAndApply() runs in MainActivity.onCreate() via setContainerDefaults()
  2. DefaultVersion.* statics are always set (volatile, needed every launch)
  3. PrefManager.* emulation defaults (presets, screen size, VRAM) are only written once per device via a deviceProfileKey guard — user customizations are preserved across restarts
  4. DXVK version selection is GPU-aware regardless of tier (SD 888 with Adreno 660 gets sarek)

Files Changed

  • New: HandheldProfileManager.kt — device detection, profile building, configuration application
  • Modified: ContainerUtils.kt — delegates setContainerDefaults() to HandheldProfileManager
  • Modified: PrefManager.kt — adds deviceProfileKey to track applied profile

Test plan

  • Verify FLAGSHIP_ELITE tier on SD 8 Elite device (AYN Odin 3 / AYANEO Pocket S2)
  • Verify FLAGSHIP tier on SD 8 Gen 2 device (AYN Odin 2)
  • Verify MID tier on SD 865 device (Retroid Pocket 5)
  • Verify LOW tier on non-Adreno device
  • Confirm user settings persist after app restart (deviceProfileKey guard)
  • Confirm DefaultVersion statics are refreshed on each launch
  • Launch a Steam/GOG/Epic game on each tier — should work without manual config

🤖 Generated with Claude Code


Summary by cubic

Auto-configures Android gaming handhelds by detecting SoC/GPU and applying optimal Turnip/DXVK/FEXCore presets. Replaces the old 3-branch GPU logic with a 5-tier system for plug-and-play game launching.

  • New Features
    • 5-tier profiles: FLAGSHIP_ELITE, FLAGSHIP, HIGH, MID, LOW with tuned Wine, DXVK, driver, VRAM, and resolution.
    • SoC-based detection via Build.SOC_MODEL (API 31+) with GPU fallback; recognizes AYN, AYANEO, Retroid, GPD models.
    • GPU-aware DXVK selection (uses sarek for Adreno 6xx and 710/720/732).
    • PrefManager.deviceProfileKey to apply defaults once per device and preserve user tweaks.
    • ContainerUtils.setContainerDefaults now delegates to HandheldProfileManager.
    • Added HandheldProfileManager.kt; updated PrefManager.kt and ContainerUtils.kt.

Written for commit 5f35b26. Summary will update on new commits.

Summary by CodeRabbit

Release Notes

  • New Features
    • Intelligent device detection now automatically configures emulation and graphics settings based on your device's processor tier and hardware capabilities.
    • User settings are now preserved across app launches, preventing automatic reconfigurations from overwriting your customizations.

Replace the 3-branch GPU if/else in setContainerDefaults() with a 5-tier
device detection system that auto-configures optimal Wine/emulation
settings based on SoC and GPU hardware.

Detection uses Build.SOC_MODEL (API 31+) with GPU renderer fallback,
covering Snapdragon 8 Elite through 855 and non-Adreno devices. Known
gaming handhelds (AYN Odin, AYANEO Pocket, Retroid Pocket, GPD XP)
are identified by manufacturer/model for logging.

Each tier configures: Turnip driver version, DXVK version, FEXCore/Box64
presets, screen resolution, video memory, and startup aggressiveness.
PrefManager settings are only written on first detection per device to
preserve user customizations across restarts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

This change introduces a centralized device profile detection and management system. A new singleton HandheldProfileManager detects device capabilities (SoC, GPU, manufacturer/model) and applies tier-based emulation/graphics settings. Configuration logic previously in ContainerUtils is consolidated here, with a new deviceProfileKey preference tracking applied profiles to avoid overwriting user customization on subsequent app launches.

Changes

Cohort / File(s) Summary
PrefManager Enhancement
app/src/main/java/app/gamenative/PrefManager.kt
Added new persistent preference deviceProfileKey (getter/setter) to store device profile identifiers and prevent settings overwrites on subsequent app launches.
Container Configuration Refactoring
app/src/main/java/app/gamenative/utils/ContainerUtils.kt
Removed device-capability conditional branches (Turnip, Adreno8 Elite handling) and replaced with delegated call to HandheldProfileManager.detectAndApply(context) for centralized device configuration.
New Device Profile Manager
app/src/main/java/app/gamenative/utils/HandheldProfileManager.kt
New singleton implementing device detection and profile-based configuration. Defines DeviceTier enum and DeviceProfile data class. Detects tier via SoC (API 31+) or GPU fallback, recognizes known handheld devices, and applies per-tier emulator/graphics/wrapper/cache settings. Guards PrefManager updates with device key to prevent user customization loss.

Sequence Diagram

sequenceDiagram
    participant App as App Launch
    participant HM as HandheldProfileManager
    participant DC as Device Detection<br/>(SoC/GPU/Model)
    participant Builder as Profile Builder
    participant DV as DefaultVersion
    participant PM as PrefManager

    App->>HM: detectAndApply(context)
    HM->>DC: detectDeviceTier(context)
    DC-->>HM: DeviceTier (FLAGSHIP/HIGH/MID/LOW)
    HM->>DC: detectHandheldName()
    DC-->>HM: device name or null
    HM->>Builder: buildProfile(tier, context)
    Builder-->>HM: DeviceProfile (settings for tier)
    HM->>DV: applyDefaultVersion(profile)
    DV-->>HM: volatile settings applied
    HM->>PM: Check deviceProfileKey
    PM-->>HM: key exists (first time or new device)
    HM->>PM: Apply PrefManager defaults from profile
    PM-->>HM: defaults set
    HM-->>App: configuration complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • feat: add toggle for auto-apply known config #586: Modifies both PrefManager and ContainerUtils to integrate preference-driven behavior and centralize device-specific configuration logic, showing a related architectural approach to device handling.

Poem

🐰 A device awakens, its profile now known,
Through tiers we detect what SoCs have shown.
No more shall defaults be lost to the wear—
HandheldProfileManager handles with care! 🎮✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: handheld auto-configuration for plug-and-play gaming' directly and clearly summarizes the main change: introducing automated handheld device configuration for gaming.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/utils/HandheldProfileManager.kt (1)

138-139: Consider using the same null/empty check as detectDeviceTier for consistent profile keys.

On API 31+, Build.SOC_MODEL might be empty on some devices. While detectDeviceTier handles this with !soc.isNullOrEmpty(), the profile key construction doesn't apply the same guard. This could lead to keys like "HIGH_" instead of "HIGH_unknown" if the SoC string is empty but tier detection fell back to GPU.

Suggested improvement
-        val soc = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Build.SOC_MODEL else "unknown"
+        val soc = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+            Build.SOC_MODEL.takeIf { !it.isNullOrEmpty() } ?: "unknown"
+        } else {
+            "unknown"
+        }
         val profileKey = "${tier.name}_${soc}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/app/gamenative/utils/HandheldProfileManager.kt` around
lines 138 - 139, In HandheldProfileManager (around where profileKey is built)
ensure the SoC value uses the same null/empty guard as detectDeviceTier: read
Build.SOC_MODEL on API >= S, then if that string is null or empty replace it
with "unknown" before constructing profileKey (currently val profileKey =
"${tier.name}_${soc}"); update the soc computation so empty strings do not
produce keys like "HIGH_" and reference detectDeviceTier behavior for how to
check !soc.isNullOrEmpty().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/app/gamenative/utils/HandheldProfileManager.kt`:
- Around line 138-139: In HandheldProfileManager (around where profileKey is
built) ensure the SoC value uses the same null/empty guard as detectDeviceTier:
read Build.SOC_MODEL on API >= S, then if that string is null or empty replace
it with "unknown" before constructing profileKey (currently val profileKey =
"${tier.name}_${soc}"); update the soc computation so empty strings do not
produce keys like "HIGH_" and reference detectDeviceTier behavior for how to
check !soc.isNullOrEmpty().

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 761d93b and 5f35b26.

📒 Files selected for processing (3)
  • app/src/main/java/app/gamenative/PrefManager.kt
  • app/src/main/java/app/gamenative/utils/ContainerUtils.kt
  • app/src/main/java/app/gamenative/utils/HandheldProfileManager.kt

@utkarshdalal
Copy link
Owner

AI slop, closing

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.

2 participants