Skip to content

Fix two crashes that prevent a fresh install from launching - #123

Open
mengelh wants to merge 1 commit into
OpenIPC:masterfrom
mengelh:fix-launch-crashes
Open

Fix two crashes that prevent a fresh install from launching#123
mengelh wants to merge 1 commit into
OpenIPC:masterfrom
mengelh:fix-launch-crashes

Conversation

@mengelh

@mengelh mengelh commented Sep 9, 2026

Copy link
Copy Markdown
  1. UnsatisfiedLinkError: libusb1.0.so / libsodium.so / libopus.so are
    linked into libWfbngRtl8812.so and libVideoNative.so via absolute
    paths in each module's CMakeLists.txt, but nothing placed them
    under a jniLibs source set, so AGP never packaged them into the
    APK and the dynamic linker couldn't find them at runtime. Only
    surfaces on a genuinely fresh install/device with no cached APK
    already carrying them (e.g. from a properly configured CI/release
    build) to mask the gap. Fixed by adding the prebuilt libraries
    (already present in each module's src/main/cpp/libs//) to a
    standard src/main/jniLibs// source set for both modules.

  2. SIGABRT in Aggregator::Aggregator ("Unable to open gs.key") /
    USB adapter lock false-refusal: WfbngLink.hpp/.cpp hardcoded both
    the gs.key path and the USB advisory lock directory as
    /data/user/0/com.openipc.pixelpilot/..., which is only correct for
    the default applicationId running as Android's default user (id
    0). Under a different applicationId (a fork/rebrand) or a
    non-default user profile (secondary user, work profile, Samsung
    Secure Folder, ...), that path doesn't exist, so opening gs.key
    fails outright, and the USB lock (see UsbDeviceLock.h) either
    silently degrades to no exclusivity or -- once the directory
    happens to resolve to a stale lock from an earlier process -- falsely
    reports "in use". Fixed by resolving both from
    Context.getFilesDir() via JNI once in the constructor instead.

Verified on-device (Galaxy Tab S7 FE, RTL8812AU): a fresh install now
launches and opens the USB adapter successfully
("USB adapter locked for exclusive access") instead of crashing
or falsely refusing the adapter.

🤖 Generated with Claude Code

1. UnsatisfiedLinkError: libusb1.0.so / libsodium.so / libopus.so are
   linked into libWfbngRtl8812.so and libVideoNative.so via absolute
   paths in each module's CMakeLists.txt, but nothing placed them
   under a jniLibs source set, so AGP never packaged them into the
   APK and the dynamic linker couldn't find them at runtime. Only
   surfaces on a genuinely fresh install/device with no cached APK
   already carrying them (e.g. from a properly configured CI/release
   build) to mask the gap. Fixed by adding the prebuilt libraries
   (already present in each module's src/main/cpp/libs/<abi>/) to a
   standard src/main/jniLibs/<abi>/ source set for both modules.

2. SIGABRT in Aggregator::Aggregator ("Unable to open gs.key") /
   USB adapter lock false-refusal: WfbngLink.hpp/.cpp hardcoded both
   the gs.key path and the USB advisory lock directory as
   /data/user/0/com.openipc.pixelpilot/..., which is only correct for
   the default applicationId running as Android's default user (id
   0). Under a different applicationId (a fork/rebrand) or a
   non-default user profile (secondary user, work profile, Samsung
   Secure Folder, ...), that path doesn't exist, so opening gs.key
   fails outright, and the USB lock (see UsbDeviceLock.h) either
   silently degrades to no exclusivity or -- once the directory
   happens to resolve to a stale lock from an earlier process -- falsely
   reports "in use". Fixed by resolving both from
   Context.getFilesDir() via JNI once in the constructor instead.

Verified on-device (Galaxy Tab S7 FE, RTL8812AU): a fresh install now
launches and opens the USB adapter successfully
("USB adapter <id> locked for exclusive access") instead of crashing
or falsely refusing the adapter.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix fresh-install native loading and app data path crashes

🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

AI Description

• Package required native dependencies for both supported Android ABIs.
• Resolve key and USB lock paths from the active application context.
• Restore fresh-install startup across rebrands and non-default Android profiles.
Diagram

graph TD
  APP["Android App"] --> APK["APK Native Libs"] --> NATIVE["Native Modules"]
  APP --> CTX["App Context"] --> JNI["JNI Resolver"] --> DIR[("Files Directory")]
  DIR --> KEY["gs.key"]
  DIR --> LOCK["USB Lock"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Canonical jniLibs prebuilts
  • ➕ Keeps one authoritative copy of each shared library.
  • ➕ Prevents linked and packaged binaries from drifting.
  • ➕ Uses Android's standard native packaging layout directly.
  • ➖ Requires updating CMake paths to link against jniLibs.
  • ➖ May require reorganizing existing static and versioned native artifacts.

Recommendation: Runtime resolution through Context.getFilesDir() is the correct portable fix. For native dependencies, consider making jniLibs the canonical prebuilt location and linking CMake targets from it; the current duplicated cpp/libs and jniLibs copies fix packaging but can diverge over time.

Files changed (8) +36 / -3 · 6 not counted

Bug fix (2) +36 / -3
WfbngLink.cppResolve native storage paths from the Android context +28/-2

Resolve native storage paths from the Android context

• Adds a JNI helper that resolves Context.getFilesDir() during construction. The resulting path is used for gs.key and USB advisory locks, removing package-name and user-profile assumptions.

app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp

WfbngLink.hppStore runtime-resolved files and key paths +8/-1

Store runtime-resolved files and key paths

• Replaces the hardcoded gs.key path with string members for the application files directory and derived key path.

app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp

Other (6)
libsodium.soPackage ARM64 sodium runtime dependency not counted

Package ARM64 sodium runtime dependency

• Adds the ARM64 libsodium shared library to the WFB module's standard jniLibs source set.

app/wfbngrtl8812/src/main/jniLibs/arm64-v8a/libsodium.so

libusb1.0.soPackage ARM64 USB runtime dependency not counted

Package ARM64 USB runtime dependency

• Adds the ARM64 libusb shared library required by the WFB native module at runtime.

app/wfbngrtl8812/src/main/jniLibs/arm64-v8a/libusb1.0.so

libsodium.soPackage 32-bit ARM sodium runtime dependency not counted

Package 32-bit ARM sodium runtime dependency

• Adds the armeabi-v7a libsodium shared library to the WFB module's APK packaging inputs.

app/wfbngrtl8812/src/main/jniLibs/armeabi-v7a/libsodium.so

libusb1.0.soPackage 32-bit ARM USB runtime dependency not counted

Package 32-bit ARM USB runtime dependency

• Adds the armeabi-v7a libusb shared library required by the WFB native module.

app/wfbngrtl8812/src/main/jniLibs/armeabi-v7a/libusb1.0.so

libopus.soPackage ARM64 Opus runtime dependency not counted

Package ARM64 Opus runtime dependency

• Adds the ARM64 libopus shared library required when loading the video native module.

app/videonative/src/main/jniLibs/arm64-v8a/libopus.so

libopus.soPackage 32-bit ARM Opus runtime dependency not counted

Package 32-bit ARM Opus runtime dependency

• Adds the armeabi-v7a libopus shared library to the video module's APK packaging inputs.

app/videonative/src/main/jniLibs/armeabi-v7a/libopus.so

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Library callers can hit a native crash 🐞 Bug ☼ Reliability
Description
resolveFilesDir passes context and each returned JNI object into subsequent calls without
checking for null values or pending exceptions. A caller constructing WfbNgLink with a null
context now reaches GetObjectClass and continues through invalid JNI results, potentially aborting
initialization instead of reporting a controlled Java error.
Code

app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp[R56-58]

+    jclass contextClass = env->GetObjectClass(context);
+    jmethodID getFilesDirMethod = env->GetMethodID(contextClass, "getFilesDir", "()Ljava/io/File;");
+    jobject filesDir = env->CallObjectMethod(context, getFilesDirMethod);
Evidence
The public Java constructor forwards its context directly to native initialization, which constructs
WfbngLink; the new constructor path immediately calls resolveFilesDir. That resolver
dereferences the context and results without null or exception checks, whereas the sole
in-repository production caller currently happens to pass a valid Activity.

app/wfbngrtl8812/src/main/java/com/openipc/wfbngrtl8812/WfbNgLink.java[53-55]
app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp[55-66]
app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp[369-373]
app/src/main/java/com/openipc/pixelpilot/VideoActivity.java[368-372]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new files-directory resolver dereferences the constructor's `Context` without validating it and continues after JNI lookup or invocation failures. This can turn a null context or pending Java exception into an uncontrolled native failure.

## Issue Context
`WfbNgLink` exposes a public constructor that forwards its argument directly to `nativeInitialize`. Validate the context before native initialization and stop immediately after any JNI exception or null result, preferably by throwing a clear Java exception rather than continuing with invalid JNI values.

## Fix Focus Areas
- app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp[55-66]
- app/wfbngrtl8812/src/main/java/com/openipc/wfbngrtl8812/WfbNgLink.java[53-55]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This changes native JNI path resolution and USB locking behavior on critical startup and device-profile paths, so it warrants a careful single-pass review.

Grey Divider

Tip of the day
💡 Did you know, you can commit Qodo's fix in one click with committable suggestions (GitHub & GitLab)

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +56 to +58
jclass contextClass = env->GetObjectClass(context);
jmethodID getFilesDirMethod = env->GetMethodID(contextClass, "getFilesDir", "()Ljava/io/File;");
jobject filesDir = env->CallObjectMethod(context, getFilesDirMethod);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Library callers can hit a native crash 🐞 Bug ☼ Reliability

resolveFilesDir passes context and each returned JNI object into subsequent calls without
checking for null values or pending exceptions. A caller constructing WfbNgLink with a null
context now reaches GetObjectClass and continues through invalid JNI results, potentially aborting
initialization instead of reporting a controlled Java error.
Agent Prompt
## Issue description
The new files-directory resolver dereferences the constructor's `Context` without validating it and continues after JNI lookup or invocation failures. This can turn a null context or pending Java exception into an uncontrolled native failure.

## Issue Context
`WfbNgLink` exposes a public constructor that forwards its argument directly to `nativeInitialize`. Validate the context before native initialization and stop immediately after any JNI exception or null result, preferably by throwing a clear Java exception rather than continuing with invalid JNI values.

## Fix Focus Areas
- app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp[55-66]
- app/wfbngrtl8812/src/main/java/com/openipc/wfbngrtl8812/WfbNgLink.java[53-55]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

1 participant