Skip to content

Start on boot: an opt-in setting for boxes without a firmware autorun (#255) - #256

Merged
compot-dev merged 8 commits into
v2from
feat/start-on-boot-255
Oct 31, 2026
Merged

compot-dev merged 8 commits into
v2from
feat/start-on-boot-255

Conversation

@compot-dev

@compot-dev compot-dev commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #255.

What

  • Start on boot checkbox in Settings (app-wide, off by default). BootReceiver gets BOOT_COMPLETED and opens Decoder when it is on; the app comes up with the saved slots and view.
  • Android 10+ starts an activity from the background only for an app that may draw over other apps. The manifest declares SYSTEM_ALERT_WINDOW; turning the setting on without it opens the system Display over other apps screen, or, where the device has none (many TV boxes), a dialog with adb shell appops set com.openipc.decoder SYSTEM_ALERT_WINDOW allow and adb shell appops write-settings (Android writes app ops to disk with a delay; a reboot soon after appops set loses it).
  • /stats.json: start_on_boot with on and overlay (allowed / missing / not needed).
  • While an activity of the app is on the screen (a firmware autorun opened it first), the receiver does nothing: a second start paused and resumed the activity and restarted every stream.
  • onNewIntent restarts the streams only for a shared link (EXTRA_TEXT), not for a plain launcher intent.
  • Reset clears it with the other settings (it lives in the same preferences).
  • Docs: docs/usage.md "Start on boot" (firmware autorun first, otherwise this setting), the /stats.json field, one line in the three READMEs.
  • 2.19.0 (new feature).

Checked

  • Docker build as in CI: testDebugUnitTest, lintDebug (no new findings besides SetTextI18n on the label, as for Mirror), assembleDebug.

Device test

Android 10 TV box (Allwinner H313), CI build of the branch, details in the comment below.

  • Setting on, no overlay permission → hint with the adb commands; reboot → no crash, Background activity start blocked, warning in the log.
  • appops set + write-settings → reboot → the app opens by itself with the saved view; /stats.json "on": true, "overlay": "allowed".
  • Setting off → reboot → the app does not start.
  • Firmware autorun and the setting both on → one start, one Start video decoder.

…evice boots (#255)

A BOOT_COMPLETED receiver opens Decoder when the setting is on. Android 10+
needs the permission to draw over other apps for that start: turning the
setting on opens the system screen for it, or shows the adb command where the
device has none. /stats.json reports start_on_boot (on, overlay).
@compot-dev compot-dev added the awaiting device test PR ready, merge only after testing on a real device label Oct 31, 2026
…s not blink the streams (#255)

Android writes app ops to disk with a delay: an appops set followed soon by a
reboot was lost on the test box, so the hint and the docs add
appops write-settings. onNewIntent restarted the streams for any intent; a
firmware autorun plus Start on boot opened the app twice and the second start
restarted the decoder. Only a shared link (EXTRA_TEXT) restarts them now.
@compot-dev
compot-dev force-pushed the feat/start-on-boot-255 branch from 5b669e7 to 6b89c7d Compare October 31, 2026 17:02
…d it already (#255)

On the test box a second start paused and resumed the activity, which
restarted every stream, so the receiver now does nothing while an activity of
the app is on the screen.
@compot-dev
compot-dev force-pushed the feat/start-on-boot-255 branch from 6b89c7d to 97a77f7 Compare October 31, 2026 17:10
@compot-dev compot-dev removed the awaiting device test PR ready, merge only after testing on a real device label Oct 31, 2026
@compot-dev

Copy link
Copy Markdown
Collaborator Author

Device test on an Android 10 TV box (Allwinner H313), CI build of 97a77f7 (2.19.0):

Case Result
Setting on, no overlay permission (the box has no Display over other apps screen) Hint dialog with the adb commands; after a reboot the start is blocked (Background activity start), the log has the warning, no crash
appops set … allow and a reboot soon after Lost: the op was back to default after the reboot. Fixed in the hint and docs with appops write-settings
appops set + write-settings, reboot Background activity start for com.openipc.decoder allowed because SYSTEM_ALERT_WINDOW permission is granted; the app opens ~60 s after power-on with the saved view; /stats.json: {"on": true, "overlay": "allowed"}
Setting off, reboot The app does not start
Firmware autorun + setting on Before bf02fbc: one window, but the second start paused and resumed the activity and restarted the decoder. Now: Start on boot: the app is open already, one Start video decoder

The box was left as found: the setting off, the op back to default, the firmware autorun cleared.

@compot-dev
compot-dev marked this pull request as ready for review October 31, 2026 17:18
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add opt-in start on boot for devices without firmware autorun

✨ Enhancement 🐞 Bug fix 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Add an off-by-default setting that opens the saved camera view after boot.
• Guide Android 10+ users through overlay permission and expose boot readiness in /stats.json.
• Avoid duplicate launches and unnecessary stream restarts when firmware autorun runs first.
Diagram

graph TD
  UI["Settings checkbox"] --> PREF["Shared preferences"] --> RX["Boot receiver"] --> CHECK{"Enabled and hidden?"}
  CHECK -->|Yes| DEC["Decoder activity"] --> STATS["Stats JSON"]
  CHECK -->|No| SKIP["Skip launch"]
  UI -->|Permission missing| PERM["Overlay permission"]
  PREF --> STATS
  PERM --> STATS
Loading
High-Level Assessment

Keep firmware autorun as the documented first choice and use the opt-in boot receiver where it is unavailable. Firmware autorun cannot provide a consistent app-controlled option across devices; the receiver also avoids a second launch when the app is already showing.

Files changed (11) +172 / -6

Enhancement (4) +136 / -4
AndroidManifest.xmlRegister boot handling and required permissions +10/-0

Register boot handling and required permissions

• Declares boot-broadcast and overlay permissions and registers an exported receiver for the protected BOOT_COMPLETED broadcast.

android/app/src/main/AndroidManifest.xml

BootReceiver.javaLaunch Decoder after boot when opted in +67/-0

Launch Decoder after boot when opted in

• Stores the off-by-default preference in settings and handles BOOT_COMPLETED. Skips a launch when Decoder is already showing, checks overlay availability, and logs failed starts.

android/app/src/main/java/com/openipc/decoder/BootReceiver.java

Decoder.javaConnect boot setting, diagnostics, and launch safeguards +29/-3

Connect boot setting, diagnostics, and launch safeguards

• Connects the Settings control to the preference and opens overlay-permission guidance when needed. Adds boot and overlay state to debug stats, tracks whether the activity is showing, and limits onNewIntent stream restarts to shared links.

android/app/src/main/java/com/openipc/decoder/Decoder.java

MenuManager.javaAdd Start on boot control and permission hint +30/-1

Add Start on boot control and permission hint

• Adds an app-wide checkbox to the Settings dialog and notifies its listener when the saved value changes. Provides adb appops instructions, including write-settings, for devices without an overlay-permission screen.

android/app/src/main/java/com/openipc/decoder/MenuManager.java

Documentation (6) +34 / -0
CHANGELOG.mdDocument the 2.19.0 release +10/-0

Document the 2.19.0 release

• Adds release notes for Start on boot, its Android permission requirement, the new stats field, and the duplicate-start stream fix.

CHANGELOG.md

README.mdLink to Start on boot guidance +1/-0

Link to Start on boot guidance

• Adds a brief English introduction and links to the usage guide.

README.md

README.ru.mdLink Russian readers to boot guidance +1/-0

Link Russian readers to boot guidance

• Adds a Russian introduction to Start on boot and links to the English usage guide.

README.ru.md

README.zh-CN.mdLink Chinese readers to boot guidance +1/-0

Link Chinese readers to boot guidance

• Adds a Chinese introduction to Start on boot and links to the English usage guide.

README.zh-CN.md

debug.mdDocument boot status in stats JSON +1/-0

Document boot status in stats JSON

• Documents the new start_on_boot object, including its on flag and overlay status values.

docs/debug.md

usage.mdExplain boot setup and device limitations +20/-0

Explain boot setup and device limitations

• Adds setup guidance that prioritizes firmware autorun, then explains the app setting and Android 10+ overlay permission. Documents adb persistence commands, stats visibility, Reset behavior, and standby limitations.

docs/usage.md

Other (1) +2 / -2
build.gradleBump Android release to 2.19.0 +2/-2

Bump Android release to 2.19.0

• Increments the version code to 48 and version name to 2.19.0.

android/app/build.gradle

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

qodo-free-for-open-source-projects Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Timeout stats omit boot status ✓ Resolved
Description
The activity timeout fallback returns device statistics without adding the enabled setting and
overlay state. When the UI thread exceeds the one-second response limit, /stats.json reaches this
fallback and omits both values even though the normal activity and no-activity paths include them.
Code

android/app/src/main/java/com/openipc/decoder/Decoder.java[1618]

+        m.put("start_on_boot", BootReceiver.state(this));
Evidence
The new boot status is added only to the normal activity state path. The timeout fallback returns
device statistics without that field, while BootReceiver.state() is the code that supplies both
the enabled and overlay values.

Remote boot-setting status
android/app/src/main/java/com/openipc/decoder/Decoder.java[1618-1618]
android/app/src/main/java/com/openipc/decoder/DebugServer.java[297-307]

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

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
Issue description
The `/stats.json` activity-timeout fallback omits the Start on boot enabled state and overlay permission state, so remote diagnostics cannot report the required configuration when the UI thread is unresponsive.
Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[1578-1618]
- android/app/src/main/java/com/openipc/decoder/BootReceiver.java[48-54]
Recommended Fix
Add `start_on_boot` using `BootReceiver.state(this)` to the timeout/device fallback returned by `debugState()`, matching the normal activity and no-activity snapshot paths. Ensure both `on` and `overlay` remain present whenever `/stats.json` is generated.

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


2. Firmware autorun opens Decoder twice ✓ Resolved
Description
BootReceiver.onReceive() checks Decoder.sShown before launching, but that flag is set only later
in Decoder.onResume(). When firmware autorun starts the activity and BOOT_COMPLETED arrives
before onResume(), the receiver sees false and issues a second activity launch request, reaching
the existing activity lifecycle.
Code

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[R50-53]

+        // which restarts every stream
+        if (Decoder.sShown) {
+            Log.i(TAG, "Start on boot: the app is open already");
+            return;
Evidence
The receiver proceeds whenever Decoder.sShown is false, while the flag is assigned true only in
onResume(). A firmware autorun can therefore be launching the activity during the interval before
onResume(), causing the boot receiver to issue a second launch; the documentation itself
identifies simultaneous autorun and the setting as the duplicate-start scenario this change is
intended to prevent.

Avoid duplicate startup with firmware autorun
android/app/src/main/java/com/openipc/decoder/BootReceiver.java[50-63]
android/app/src/main/java/com/openipc/decoder/Decoder.java[2503-2506]
android/app/src/main/java/com/openipc/decoder/Decoder.java[2661-2672]
docs/usage.md[125-129]

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 duplicate-start guard relies on `sShown`, which is set only in `onResume()`. A firmware autorun can begin launching `Decoder` while `sShown` is still false, allowing the boot receiver to issue a second launch request.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/BootReceiver.java[50-63]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[2503-2506]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[2661-2672]
## Recommended Fix
Add an atomic startup reservation or another process-safe duplicate-launch guard that is set before `BootReceiver` calls `startActivity()`, and clear it only when the launch is no longer pending. Ensure firmware autorun and `BOOT_COMPLETED` cannot both issue startup launches during the activity creation/resume window.

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


3. README languages lack boot sections ✓ Resolved
Description
The three README files add only a one-line English link rather than a short Start on boot section
with the required guidance. The firmware-autorun-first and Decoder-setting-otherwise recommendation
therefore remains only in the English usage page instead of appearing in all three README languages.
Code

README.ru.md[69]

+   **Start on boot** открывает приложение само после перезапуска устройства — для приставки, которая только показывает камеры: [Start on boot](docs/usage.md#start-on-boot) (на английском).
Evidence
Each README adds only a single link line, while the detailed firmware-autorun and fallback-setting
guidance is present in the English usage document. This does not satisfy the requirement for a short
section in all three README languages.

Multilingual Start on boot documentation
README.md[69-69]
README.ru.md[69-69]
README.zh-CN.md[69-69]
docs/usage.md[123-138]

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

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
Issue description
The three README files link to the English usage page but do not include the required short Start on boot guidance in each language, including the recommendation to prefer firmware autorun when available and use Decoder's setting otherwise.
Fix Focus Areas
- README.md[69-69]
- README.ru.md[69-69]
- README.zh-CN.md[69-69]
Recommended Fix
Add a short Start on boot section to each README, localized to that README's language, recommending the device's firmware autorun where available and Decoder's Start on boot setting otherwise. Keep the existing usage-document link for detailed instructions.

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



Remediation recommended

4. Boot start on Android 15+ may still be blocked 🐞 Bug ≡ Correctness
Description
onReceive calls showOverlay() and then calls context.startActivity(start) straight away, in
the same main-thread turn. wm.addView only queues the window: the 1×1 view has not been laid out,
drawn or put on screen when startActivity runs, so the overlay may not count as visible yet when
Android 15+ decides whether to allow the background start. In that case the start is blocked even
with the permission granted, the 2 s postDelayed only removes the overlay afterwards, and the
Android 10 device test does not cover this path.
Code

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[R81-84]

+        View overlay = Build.VERSION.SDK_INT >= 35 && overlayAllowed(context)
+                ? showOverlay(context) : null;
+        try {
+            context.startActivity(start);
Evidence
In BootReceiver.java lines 81-84, showOverlay(context) is followed immediately by
context.startActivity(start), and nothing waits for the view to be drawn first. showOverlay
(lines 102-117) only calls wm.addView and returns. The Handler at lines 89-93 runs only after the
start, to remove the overlay. Android draws a newly added window later, on a separate pass, so the
window is not yet on screen when startActivity runs. The device test used an Android 10 box only,
where this code does not run (SDK_INT >= 35).

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[79-117]

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

## Issue description
On Android 15+ the boot receiver adds a transparent overlay window and calls startActivity in the same main-thread turn. The window has not been drawn yet, so the background start may still be blocked.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/BootReceiver.java[81-94]
## Recommended Fix
When an overlay is shown, call goAsync() right away. Then call startActivity only once the view has been drawn: for example from a ViewTreeObserver.OnDrawListener / OnPreDrawListener on the overlay view, or from a short postDelayed (a few hundred ms) on the main Handler. Remove the overlay and call pending.finish() OVERLAY_MS after the start. Keep the immediate start when no overlay is shown. Log when the start is attempted, so a failed start on Android 15+ can be diagnosed.

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


5. Backgrounded apps stay hidden after boot ✓ Resolved
Description
BootReceiver.onReceive() treats Decoder.sAlive > 0 as proof that the app is already on screen,
but the count remains positive after Decoder.onPause(). If Decoder opens before BOOT_COMPLETED
and another activity comes to the foreground, the receiver returns without bringing Decoder back,
even though Start on boot is enabled.
Code

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[R69-71]

+        if (Decoder.sAlive.get() > 0) {
+            Log.i(TAG, "Start on boot: the app is open already");
+            return;
Evidence
The new guard uses an onCreate-to-onDestroy count, while onPause stops the streams without reducing
that count. An activity can therefore remain counted after it leaves the foreground, and the
receiver exits before its startActivity call.

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[64-84]
android/app/src/main/java/com/openipc/decoder/Decoder.java[190-194]
android/app/src/main/java/com/openipc/decoder/Decoder.java[2501-2512]
android/app/src/main/java/com/openipc/decoder/Decoder.java[2597-2604]

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 boot receiver skips its launch whenever a Decoder activity exists, including when that activity is paused behind another app. Start on boot then fails to bring Decoder onto the screen.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/BootReceiver.java[67-72]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[193-193]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[2501-2507]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[2597-2604]
## Recommended Fix
Track whether an existing Decoder activity is visible or still opening, separately from whether it merely exists. Skip the boot launch for a visible or in-flight opening activity, but bring Decoder to the foreground when the existing activity is backgrounded.

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


6. Boot start is likely blocked on Android 15+ ✓ Resolved
Description
overlayAllowed() treats Settings.canDrawOverlays() as enough for BootReceiver.onReceive() to
start Decoder from the background, but the app targets SDK 36 and never shows an overlay window.
On Android 15+ the overlay exception for apps targeting 35+ applies only while one of the app's
overlay windows is visible, so the boot start would be blocked there and /stats.json would still
report "overlay": "allowed".
Code

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[R44-46]

+    static boolean overlayAllowed(Context context) {
+        return !overlayNeeded() || Settings.canDrawOverlays(context);
+    }
Evidence
build.gradle sets targetSdk 36. The receiver calls startActivity straight from BOOT_COMPLETED and
creates no overlay window, so the only background-start exception it relies on is holding the
overlay permission. As far as I know, Android 15 made that exception stricter for apps targeting
35+: the app also needs a visible overlay window, which this code never shows. This rule comes from
Android, not from this repo, and the PR's device test covered only Android 10. state() reports
"allowed" from canDrawOverlays alone.

android/app/src/main/java/com/openipc/decoder/BootReceiver.java[40-78]
android/app/build.gradle[23-27]

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

## Issue description
On Android 15+ (API 35), apps targeting 35 or higher that hold SYSTEM_ALERT_WINDOW can start an activity from the background only while one of their overlay windows is visible. BootReceiver starts Decoder from BOOT_COMPLETED with no overlay window, so the start is likely blocked on those devices, while /stats.json reports "allowed".
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/BootReceiver.java[40-78]
## Recommended Fix
On API 35+, briefly add a tiny TYPE_APPLICATION_OVERLAY window through WindowManager before calling startActivity, and remove it afterwards (or once Decoder is created). Another option is a full-screen-intent notification. Then test on an Android 15 device. Also make state() report a distinct value (for example "allowed, needs overlay window") on API 35+ until this is confirmed working.

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


View review recommended (2)
7. Remote boot status disappears after exit ✓ Resolved
Description
debugState() adds start_on_boot only to snapshots supplied by a live Decoder activity. If the
activity is destroyed while the debug server remains running, /stats.json takes its no-activity
branch and omits both the saved setting and overlay status, even though neither value requires an
activity.
Code

android/app/src/main/java/com/openipc/decoder/Decoder.java[R1618-1621]

+        boot.put("on", BootReceiver.enabled(this));
+        boot.put("overlay", !BootReceiver.overlayNeeded() ? "not needed"
+                : BootReceiver.overlayAllowed(this) ? "allowed" : "missing");
+        m.put("start_on_boot", boot);
Evidence
The server is kept for the process lifetime, but activity destruction clears its source. Requests
without a source use a separate three-field response, bypassing the newly added activity-only
fields.

android/app/src/main/java/com/openipc/decoder/DebugServer.java[99-114]
android/app/src/main/java/com/openipc/decoder/Decoder.java[2600-2606]
android/app/src/main/java/com/openipc/decoder/DebugServer.java[294-303]
android/app/src/main/java/com/openipc/decoder/Decoder.java[1617-1621]

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

## Issue description
`start_on_boot` is absent from `/stats.json` when the debug server is running without a `Decoder` activity, so remote clients cannot read the app-wide boot setting in that state.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[1617-1621]
- android/app/src/main/java/com/openipc/decoder/DebugServer.java[294-303]
## Recommended Fix
Use a shared helper for the boot preference and overlay status, and add its result to the no-activity snapshot as well as normal activity snapshots.

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


8. Phone users cannot reach the boot setting ✓ Resolved
Description
showUrlEditor() appends the Start on boot checkbox to an unscrollable vertical dialog view. On a
short landscape display, especially when the requested keyboard is visible, the URL field, two
option rows, Mirror checkbox, title, and buttons can consume the available height and leave the new
checkbox clipped with no way to scroll to it.
Code

android/app/src/main/java/com/openipc/decoder/MenuManager.java[604]

+        content.addView(boot);
Evidence
The activity is locked to landscape, and the dialog requests the keyboard. Its custom view is a
vertical LinearLayout with only the Turn row horizontally scrollable; the newly added checkbox is
its last child, below all existing settings.

android/app/src/main/AndroidManifest.xml[49-54]
android/app/src/main/java/com/openipc/decoder/MenuManager.java[581-605]
android/app/src/main/java/com/openipc/decoder/MenuManager.java[606-627]

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 Start on boot checkbox can be clipped below the visible Settings dialog on short landscape screens, with no vertical way to reach it.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/MenuManager.java[581-605]
- android/app/src/main/java/com/openipc/decoder/MenuManager.java[624-627]
## Recommended Fix
Place the dialog's vertical settings content inside a vertically scrollable container while retaining the existing horizontal scrolling for the Turn row. Verify that Start on boot and Save remain reachable on a small landscape screen with the soft keyboard open.

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


Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Findings visible per group, which tucks the rest behind a View link

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread README.ru.md Resolved
…e READMEs (Qodo on #256)

On a short landscape screen with the keyboard up, the new checkbox could end
up below the dialog with no way to reach it. The READMEs get the short section
the issue asked for: the device's own autorun first, otherwise the setting.
@compot-dev
compot-dev force-pushed the feat/start-on-boot-255 branch from 97a77f7 to ded13e9 Compare October 31, 2026 17:40
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit ded13e9

…ats.json has it without an activity (Qodo on #256)

A firmware autorun that is still creating the activity when BOOT_COMPLETED
arrives no longer gets a second start: the receiver checks for any Decoder
activity alive (onCreate to onDestroy). The no-activity snapshot of the debug
server reports start_on_boot too.
@compot-dev
compot-dev force-pushed the feat/start-on-boot-255 branch from ded13e9 to 4de2f6c Compare October 31, 2026 17:50
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 4de2f6c

…n_boot also when the UI thread hangs (Qodo on #256)

Android 15 lets an app that targets 35+ start an activity from the background
with SYSTEM_ALERT_WINDOW only while one of its overlay windows is visible, so
the receiver adds a transparent 1x1 overlay for two seconds around the start.
start_on_boot moves to the part of /stats.json that needs no UI state.
@compot-dev
compot-dev force-pushed the feat/start-on-boot-255 branch from 4de2f6c to 82375a2 Compare October 31, 2026 18:04
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 82375a2

@compot-dev
compot-dev force-pushed the feat/start-on-boot-255 branch from 82375a2 to cbee135 Compare October 31, 2026 18:08
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment on lines +81 to +84
View overlay = Build.VERSION.SDK_INT >= 35 && overlayAllowed(context)
? showOverlay(context) : null;
try {
context.startActivity(start);

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

4. Boot start on android 15+ may still be blocked 🐞 Bug ≡ Correctness

onReceive calls showOverlay() and then calls context.startActivity(start) straight away, in
the same main-thread turn. wm.addView only queues the window: the 1×1 view has not been laid out,
drawn or put on screen when startActivity runs, so the overlay may not count as visible yet when
Android 15+ decides whether to allow the background start. In that case the start is blocked even
with the permission granted, the 2 s postDelayed only removes the overlay afterwards, and the
Android 10 device test does not cover this path.
Agent Prompt
## Issue description
On Android 15+ the boot receiver adds a transparent overlay window and calls startActivity in the same main-thread turn. The window has not been drawn yet, so the background start may still be blocked.

## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/BootReceiver.java[81-94]

## Recommended Fix
When an overlay is shown, call goAsync() right away. Then call startActivity only once the view has been drawn: for example from a ViewTreeObserver.OnDrawListener / OnPreDrawListener on the overlay view, or from a short postDelayed (a few hundred ms) on the main Handler. Remove the overlay and call pending.finish() OVERLAY_MS after the start. Keep the immediate start when no overlay is shown. Log when the start is attempted, so a failed start on Android 15+ can be diagnosed.

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

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit cbee135

@compot-dev

Copy link
Copy Markdown
Collaborator Author

Re-tested on the Android 10 TV box with the CI build of cbee135 (final head):

  • Firmware autorun + Start on boot: one Start video decoder; the receiver logs Start on boot: the app is open already.
  • Start on boot only (firmware autorun cleared): Background activity start for com.openipc.decoder allowed because SYSTEM_ALERT_WINDOW permission is granted, the app opens with the saved view.

Not tested on Android 15+ (the 1x1 overlay path): no Android 15 device available for it right now.

The box was left as found (setting off, app op default, firmware autorun cleared).

@compot-dev
compot-dev merged commit d648fc5 into v2 Oct 31, 2026
7 checks passed
@compot-dev
compot-dev deleted the feat/start-on-boot-255 branch October 31, 2026 18:24
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.

Start on boot: an opt-in setting for boxes without a firmware autorun

1 participant