Skip to content
This repository was archived by the owner on Jun 20, 2026. It is now read-only.

SpeedCool App v2.4 - Android Application with Root & Shizuku - #6

Open
Llucs wants to merge 16 commits into
mainfrom
app-v2.4
Open

Llucs wants to merge 16 commits into
mainfrom
app-v2.4

Conversation

@Llucs

@Llucs Llucs commented May 26, 2026 •

Copy link
Copy Markdown
Owner

Aplicativo Android SpeedCool v2.4 com suporte a Root e Shizuku

Summary by CodeRabbit

  • New Features

    • Launched SpeedCool Android app with device optimization functionality.
    • Added Dashboard for real-time system status (CPU, GPU, RAM, temperature, battery) and profile switching.
    • Introduced three performance profiles: Eco, Balanced, and Performance modes.
    • Added automatic conflict detection and resolution for system stability.
    • Implemented background optimization service with intelligent RAM cleaning and profile auto-switching.
    • Added customizable settings for auto-start, temperature units, and learning mode.
    • Integrated support for both root and Shizuku execution methods.
  • Documentation

    • Added project README.

Review Change Stack

Llucs added 5 commits May 26, 2026 12:19
Full-featured Android application for SpeedCool performance optimization:
• Root and Shizuku execution modes
• Real-time system monitoring (CPU, RAM, GPU, temp, battery)
• Performance profiles: Eco, Balanced, Performance
• Adaptive optimization engine
• Thermal management and monitoring
• RAM management with auto-clean
• Conflict detection and resolution
• Background optimization service
• Material Design 3 UI with Jetpack Compose
@coderabbitai

coderabbitai Bot commented May 26, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@Llucs, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 41 minutes and 20 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f657efcd-e640-4156-8572-4add4c7e2b38

📥 Commits

Reviewing files that changed from the base of the PR and between bb2c93f and aef5287.

📒 Files selected for processing (7)
  • app/src/main/java/com/speedcool/app/engine/ConflictDetector.kt
  • app/src/main/java/com/speedcool/app/engine/OptimizationEngine.kt
  • app/src/main/java/com/speedcool/app/root/ShellExecutor.kt
  • app/src/main/java/com/speedcool/app/ui/SpeedCoolNavHost.kt
  • app/src/main/java/com/speedcool/app/ui/components/Common.kt
  • app/src/main/java/com/speedcool/app/ui/screens/SettingsScreen.kt
  • app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt
📝 Walkthrough

Walkthrough

A complete Android application implementation is added, comprising a performance optimization system with Compose UI, background monitoring service, dual-mode shell execution (root/Shizuku), and system management engines for CPU/GPU/thermal/RAM tuning. The app launches on boot, continuously monitors system status, applies optimization profiles based on thresholds, and provides a three-screen dashboard for user control.

Changes

SpeedCool Android App Implementation

Layer / File(s) Summary
Build System and Dependencies
build.gradle.kts, app/build.gradle.kts, gradle.properties, gradle/wrapper/gradle-wrapper.properties, gradlew, gradlew.bat, settings.gradle.kts
Gradle 8.5 wrapper, Android 8.2.2 and Kotlin 1.9.22 plugins, AndroidX/Compose BOM, Shizuku, DataStore, and Coroutines dependencies; repositories configured for Google, Maven Central, and Jitpack.
Core Data Models and Persistence
app/src/main/java/com/speedcool/app/data/Models.kt, app/src/main/java/com/speedcool/app/data/SettingsData.kt
Domain enums (Profile, ExecutorMode) and data classes (SystemStatus, ConflictInfo, OptimizationResult) for representing device state; DataStore-backed SettingsData with typed preferences and suspend update methods for engine mode, profile, and monitoring settings.
Privileged Execution Framework
app/src/main/java/com/speedcool/app/root/ShellExecutor.kt
ShellExecutor interface, RootExecutor (su -c + persistent shell for batch), ShizukuExecutor (Shizuku IPC), and ExecutorFactory for dynamic selection with availability probing.
System Management Engines
app/src/main/java/com/speedcool/app/engine/PerformanceManager.kt, app/src/main/java/com/speedcool/app/engine/ThermalManager.kt, app/src/main/java/com/speedcool/app/engine/RAMManager.kt, app/src/main/java/com/speedcool/app/engine/ConflictDetector.kt, app/src/main/java/com/speedcool/app/engine/OptimizationEngine.kt
PerformanceManager applies CPU/GPU/I/O tuning per profile; ThermalManager reads CPU/battery metrics; RAMManager manages memory and swappiness; ConflictDetector identifies unsafe modules/governors and provides chipset detection; OptimizationEngine orchestrates all managers and handles initialization/status collection.
Android Bootstrap and Resources
app/src/main/java/com/speedcool/app/SpeedCoolApp.kt, app/src/main/java/com/speedcool/app/MainActivity.kt, app/src/main/AndroidManifest.xml, app/proguard-rules.pro, app/src/main/java/com/speedcool/app/ui/theme/Color.kt, app/src/main/java/com/speedcool/app/ui/theme/Theme.kt, app/src/main/res/drawable/ic_launcher_foreground.xml, app/src/main/res/values/colors.xml, app/src/main/res/values/strings.xml, app/src/main/res/values/themes.xml
Application class with settings/notification initialization, MainActivity entry point with edge-to-edge Compose setup, manifest declaring permissions/components/Shizuku integration, ProGuard rules, and color/theme/drawable resources.
Background Service and Boot Auto-start
app/src/main/java/com/speedcool/app/service/SpeedCoolService.kt, app/src/main/java/com/speedcool/app/service/BootReceiver.kt
SpeedCoolService runs foreground with persistent notification, initializes engine once then loops every 30 seconds applying profiles based on CPU/RAM thresholds; BootReceiver starts service on device boot.
Navigation and UI Screens
app/src/main/java/com/speedcool/app/ui/SpeedCoolNavHost.kt, app/src/main/java/com/speedcool/app/ui/components/Common.kt, app/src/main/java/com/speedcool/app/ui/screens/DashboardScreen.kt, app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt, app/src/main/java/com/speedcool/app/ui/screens/SettingsScreen.kt
SpeedCoolNavHost manages bottom-tab navigation to Dashboard, Status, and Settings screens; Dashboard displays profile selector, stat cards, and auto-refresh toggle; StatusScreen shows scrollable system details with threshold-based colors; SettingsScreen groups configuration toggles; Common.kt provides StatCard, ProfileSelector, TempGauge (canvas arc), and RamBar (canvas progress) composables.
Continuous Integration Workflow
.github/workflows/android-app.yml
GitHub Actions workflow builds debug APK on manual dispatch or push to app-v2.4 branch; uploads artifact as SpeedCoolApp-Debug.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes


🐰 A garden of code springs to life,
Shell commands taming device strife,
Profiles dance through CPU's beat,
Compose screens keep performance sweet! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main deliverable: a complete Android application (SpeedCool App v2.4) with dual execution support (Root & Shizuku), which matches the comprehensive changeset of a full Android app implementation with multiple engine components, UI, and build configuration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch app-v2.4

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d4f0391f88

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +39 to +41
writer.write("$cmd\n")
writer.flush()
results.add(reader.readLine() ?: "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid blocking batch execution on missing command output

executeBatch() reads one line from stdout after every command, but most of the queued commands (for example echo ... > /sys/...) produce no stdout at all. In that case readLine() blocks waiting for a newline/EOF, so profile application and conflict resolution can hang indefinitely instead of completing.

Useful? React with 👍 / 👎.

Comment on lines +83 to +90
onStartService = {
scope.launch {
isServiceRunning = true
executorMode = engine.getExecutor()?.mode ?: "none"
}
},
onStopService = {
isServiceRunning = false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Start and stop the real service from dashboard actions

The dashboard's start/stop handlers only flip local Compose state and never call startForegroundService()/stopService(), so tapping “Iniciar/Parar” does not actually control SpeedCoolService. Users can believe optimization is running while no background service exists once the UI leaves composition.

Useful? React with 👍 / 👎.

Comment on lines +108 to +121
autoStart = false,
backgroundService = true,
autoRamClean = true,
learningEnabled = true,
conflictAutoResolve = true,
tempUnit = "celsius",
ramCleanInterval = 180,
onAutoStartChange = {},
onBackgroundServiceChange = {},
onAutoRamCleanChange = {},
onLearningEnabledChange = {},
onConflictAutoResolveChange = {},
onTempUnitChange = {},
onRamCleanIntervalChange = {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind settings screen to persisted state instead of constants

The settings route passes hard-coded values and no-op callbacks into SettingsScreen, so switches/sliders cannot persist or even reflect user changes. This makes core controls like auto-start/background service effectively non-functional despite the presence of a SettingsData store.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🧹 Nitpick comments (5)
.github/workflows/android-app.yml (1)

18-19: ⚡ Quick win

Avoid suppressing errors in SDK setup commands.

The || true on line 18 and output redirection on line 19 swallow all errors, making build failures difficult to diagnose. If sdkmanager fails to install components, the subsequent gradle build will fail with confusing errors.

Additionally, when running sdkmanager from a non-standard location, explicitly passing --sdk_root=$ANDROID_HOME ensures it locates the SDK correctly.

🔧 Proposed fix to improve error visibility and SDK setup robustness
-        yes | sdkmanager --licenses > /dev/null 2>&1 || true
-        sdkmanager "platforms;android-34" "build-tools;34.0.0" > /dev/null 2>&1
+        yes | sdkmanager --sdk_root=$ANDROID_HOME --licenses || true
+        sdkmanager --sdk_root=$ANDROID_HOME "platforms;android-34" "build-tools;34.0.0"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/android-app.yml around lines 18 - 19, Remove the
error-suppression and output-redirection around the sdkmanager calls so failures
are visible: delete the "|| true" and the "> /dev/null 2>&1" redirections on the
lines invoking sdkmanager, and instead let the command return a non-zero exit
code (or explicitly check its exit status and exit 1 on failure). Also make the
commands robust by adding the SDK root flag (use --sdk_root="$ANDROID_HOME") to
both the license acceptance invocation (e.g., sdkmanager --licenses) and the
package install invocation (sdkmanager "platforms;android-34"
"build-tools;34.0.0"), so the workflow fails loudly if sdkmanager cannot find or
install components.
gradlew.bat (1)

17-92: ⚡ Quick win

Consider using the official Gradle wrapper script.

Like gradlew, this appears to be a simplified custom wrapper. The official Gradle-generated gradlew.bat includes additional error handling, proper path resolution, and has been battle-tested across diverse Windows environments.

Generate the official wrapper by running:

gradle wrapper --gradle-version 8.5
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gradlew.bat` around lines 17 - 92, The current gradlew.bat is a simplified
custom wrapper missing the official Gradle wrapper's robust error handling and
path resolution; replace this file with the official Gradle-generated script by
running "gradle wrapper --gradle-version 8.5" in the project root and committing
the generated gradlew.bat (and associated gradle/wrapper files), ensuring the
new script preserves proper handling around symbols/labels shown in the diff
such as DEFAULT_JVM_OPTS, findJavaFromJavaHome, :execute, :fail and the
CLASSPATH/GradleWrapperMain invocation so you get the battle-tested behavior for
Windows environments.
.gradle/buildOutputCleanup/cache.properties (1)

1-2: 💤 Low value

Consider excluding Gradle build cache from version control.

The .gradle/ directory contains build cache and is typically excluded via .gitignore. While including it is harmless, it adds unnecessary files to the repository.

Add to .gitignore:

.gradle/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.gradle/buildOutputCleanup/cache.properties around lines 1 - 2, The
repository currently contains the generated Gradle cache file cache.properties
under the .gradle directory which should be excluded from VCS; update the
project's .gitignore to add the entry ".gradle/" and then remove the tracked
.gradle files from the index (e.g., git rm -r --cached .gradle) and commit the
change so the cached build files (cache.properties) are no longer versioned.
gradle/wrapper/gradle-wrapper.properties (1)

3-3: Validate Gradle wrapper version (compatibility + security)

Gradle 8.5 is compatible with Android Gradle Plugin 8.2.2 (AGP 8.2 requires minimum Gradle 8.2). The Gradle-core security advisories found are patched in Gradle 6.0 and 5.4.0, so they don’t impact Gradle 8.5. Latest Gradle (as of 2026-05-26) is 9.5.1—upgrade only if your AGP/project constraints allow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gradle/wrapper/gradle-wrapper.properties` at line 3, The Gradle wrapper
distributionUrl currently pins Gradle 8.5; validate compatibility with your
Android Gradle Plugin (AGP) and project constraints and then either keep 8.5 or
upgrade the distributionUrl to a vetted newer Gradle (e.g., 9.5.1) if
AGP/project allow; update the distributionUrl entry accordingly and add a short
comment or upgrade note in your repo describing the AGP version constraint so
future reviewers know why you chose 8.5 versus a newer Gradle.
app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt (1)

135-140: ⚡ Quick win

Rename function to match its actual purpose.

The function is named executorModeDisplay but it maps Profile enum values, not ExecutorMode. Based on the review context, ExecutorMode is a separate domain model (likely representing Root vs. Shizuku execution modes).

Rename to profileDisplay or profileDisplayName for clarity.

♻️ Proposed refactor
-private fun executorModeDisplay(profile: Profile): String = when (profile) {
+private fun profileDisplay(profile: Profile): String = when (profile) {
     Profile.ECO -> "Eco"
     Profile.BALANCED -> "Equilibrado"
     Profile.PERFORMANCE -> "Performance"
     Profile.LEARNING -> "Aprendizado"
 }

And update the call site on line 103:

-                StatusItem("Modo", executorModeDisplay(status.activeProfile))
+                StatusItem("Modo", profileDisplay(status.activeProfile))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt` around lines
135 - 140, Rename the function executorModeDisplay to profileDisplayName (or
profileDisplay) because it maps Profile enum values, not ExecutorMode; update
the function declaration private fun executorModeDisplay(profile: Profile):
String to the new name (e.g., private fun profileDisplayName(profile: Profile):
String) and change all call sites that invoke executorModeDisplay(...) (for
example the call at the previously noted call site around line 103) to use the
new name so callers compile cleanly; leave the when mapping of Profile.ECO,
Profile.BALANCED, Profile.PERFORMANCE, Profile.LEARNING unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/android-app.yml:
- Around line 7-11: Pin the reusable GitHub Actions and disable credential
persistence: replace mutable tags like actions/checkout@v4 and
actions/setup-java@v4 with their pinned commit SHAs (use the specific commit SHA
for actions/checkout and actions/setup-java) and add persist-credentials: false
under the actions/checkout step to prevent leaking git auth; also pin any other
actions used (e.g., actions/upload-artifact) to their SHAs to eliminate
supply-chain risk.

In `@app/proguard-rules.pro`:
- Line 2: The proguard rule "-keep class com.speedcool.app.** { *; }" is too
broad and disables R8 obfuscation; replace it by removing the blanket keep and
instead add narrow keep rules only for types/members that are reflectively
accessed or required by frameworks (e.g., classes referenced via Class.forName,
Gson/Jackson model classes, Room entities/DAOs, Parcelable implementations,
Android components like Activities/Services/BroadcastReceivers). Audit usages of
reflection/serialization and add targeted rules such as -keep,
-keepclassmembers, or -keepnames for those specific fully-qualified classes
(referencing the com.speedcool.app package names of the affected classes) rather
than keeping com.speedcool.app.** wholesale. Ensure Android components remain
kept/instantiable and any serialization-mapped model fields used by Gson/Jackson
are preserved.

In `@app/src/main/AndroidManifest.xml`:
- Line 18: Replace the hard-coded app label "SpeedCool" in the Android manifest
with a string resource reference: update the android:label attribute (in
AndroidManifest.xml) to use `@string/app_name` and ensure the app_name entry
exists in res/values/strings.xml; if missing, add app_name="SpeedCool" (or
localized values) to strings.xml so the manifest references a resource rather
than a literal.
- Line 9: Remove the unnecessary uses-permission entry for
android.permission.REQUEST_INSTALL_PACKAGES from the manifest (no
PackageInstaller/ACTION_INSTALL_PACKAGE usage in the codebase); also replace the
hardcoded android:label="SpeedCool" attribute with the string resource reference
android:label="`@string/app_name`" so the app uses the localized value from
res/values/strings.xml.

In `@app/src/main/java/com/speedcool/app/data/SettingsData.kt`:
- Around line 54-66: The settingsFlow currently maps context.dataStore.data
directly and will crash on DataStore corruption; wrap the upstream flow with a
catch that converts CorruptionException into a safe fallback (e.g.,
emit(emptyPreferences())) before the map so the collector won't fail.
Concretely, update settingsFlow to use context.dataStore.data.catch { e -> if (e
is CorruptionException) { /* log */ emit(emptyPreferences()) } else throw e } .
Then keep the existing .map { prefs -> Settings(...) } unchanged; reference
symbols: settingsFlow, context.dataStore.data, CorruptionException,
emptyPreferences().

In `@app/src/main/java/com/speedcool/app/engine/OptimizationEngine.kt`:
- Line 70: The summary flag conflictsDetected in OptimizationEngine.kt currently
checks only conflictingModules and suspiciousGovernors; update its condition to
also consider disabled thermal zones by including
conflicts.thermalZonesOff.isNotEmpty() (or the appropriate thermalZonesOff
predicate) in the OR expression so any disabled thermal zone will set
conflictsDetected to true; modify the assignment that sets conflictsDetected and
ensure it still guards against conflicts being null.
- Around line 13-16: SystemStatus.conflictsDetected currently omits
ConflictInfo.thermalZonesOff and the manager fields (perfMan, thermMan, ramMan,
conflictDetector) are lazy based on nullable executor causing them to remain
null if called before initialize(); modify conflictsDetected to include
thermalZonesOff in its combined check, and change manager lifecycle so they are
created during initialize() (using the non-null executor) and explicitly nulled
in cleanup(); also update checkConflicts(), resolveConflicts(), and cleanRam()
to guard against uninitialized managers by either requiring initialize()
(throw/early-return) or checking for null and no-op, ensuring managers are not
permanently locked as null.

In `@app/src/main/java/com/speedcool/app/engine/PerformanceManager.kt`:
- Around line 20-22: The shell arithmetic currently references an undefined
shell variable `percent`, causing incorrect limits; update the cmds.add call
that builds the arithmetic string in PerformanceManager (where the two cmds.add
lines are created) to inject the Kotlin `percent` argument via string
interpolation (e.g., use ${percent} inside the Kotlin string) so the resulting
shell command becomes echo $((val * <actual_percent> / 100)) and continues to
escape shell variables like $val and $cpu as before.
- Around line 41-65: applyProfile currently ignores failures by only using
onSuccess and then treating at-least-one-success as overall success; change it
to fail-fast: for each call to setCpuGovernor, setCpuFreqLimit, setIOScheduler,
and optimizeGpu inside applyProfile, capture the Result return, if it's failure
immediately return Result.failure(result.exceptionOrNull() ?:
RuntimeException("...")), otherwise append the success value and continue; do
this for every branch (Profile.ECO, Profile.PERFORMANCE, default) so any failing
step short-circuits and returns the underlying error instead of masking partial
application.

In `@app/src/main/java/com/speedcool/app/root/ShellExecutor.kt`:
- Around line 31-46: The batch executor blocks on reader.readLine() for
stdout-silent commands in executeBatch; change RootExecutor.executeBatch and
ShizukuExecutor.executeBatch so you do not call reader.readLine() once per
command synchronously—write all commands (or write and flush each command) then
close the writer (or send "exit\n") and drain the process streams until EOF
instead of blocking per-command: after sending commands, read from
process.inputStream and process.errorStream fully (e.g., loop reading lines
until null or until process.waitFor() completes) to collect stdout/stderr for
the whole batch, capture stderr content into results or a separate error list,
call process.waitFor() and check process.exitValue() and return Result.failure
when non-zero, and ensure reader/writer/process are closed to avoid leaks;
reference executeBatch, reader.readLine, writer, process.waitFor, and
process.exitValue when locating the code to change.

In `@app/src/main/java/com/speedcool/app/service/SpeedCoolService.kt`:
- Around line 35-53: The periodic optimization loop inside the scope.launch in
SpeedCoolService.kt can be killed by any exception from engine?.collectStatus(),
applyProfile(), or cleanRam(); wrap the per-iteration logic (the block that
calls engine.initialize(...), collectStatus(), applyProfile(...), and
cleanRam()) in a try-catch that catches Throwable, logs the error (including the
exception details) via your logger, and continues to the next delay so one
failure doesn't cancel the coroutine; ensure the try-catch surrounds each
iteration (not the whole coroutine startup) and still respects the existing
delay(30000) behavior.

In `@app/src/main/java/com/speedcool/app/SpeedCoolApp.kt`:
- Around line 24-28: The notification channel name/description are hardcoded in
the channel creation (the NotificationChannel instantiation in SpeedCoolApp.kt);
replace the literal strings with resource lookups by adding two string resources
(e.g., notification_channel_name and notification_channel_description) in
res/values/strings.xml and use
context.getString(R.string.notification_channel_name) and
context.getString(R.string.notification_channel_description) when constructing
the NotificationChannel so the user-visible text is localized and centrally
managed.

In `@app/src/main/java/com/speedcool/app/ui/components/Common.kt`:
- Around line 153-154: Clamp the usagePercent to the 0–100 range before
computing the bar width so out-of-range values can't produce invalid sizes:
replace the direct use of usagePercent in the Size constructor with a clamped
value (e.g., val clamped = usagePercent.coerceIn(0f, 100f)) and use clamped in
Size(size.width * (clamped / 100f), size.height); keep the CornerRadius line
unchanged.
- Around line 42-43: StatCard is currently referencing the composable lambda
icon without invoking it—change the reference to call icon() where the icon
should be emitted (look for the icon: `@Composable` () -> Unit parameter and the
place that currently just mentions icon). In RamBar, clamp the usagePercent
input to the 0..100 range before computing widths (use something like
usagePercent.coerceIn(0f, 100f) and then compute the fraction or dp width from
that clamped value) so bar sizing cannot be driven outside expected bounds;
update any calculations that derive filledWidth from usagePercent to use the
clamped value.

In `@app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt`:
- Line 103: The UI label "Modo" is misleading because StatusItem("Modo",
executorModeDisplay(status.activeProfile)) actually shows the performance
profile (status.activeProfile) not the executor mode; update the label to
"Perfil" to match the data, and optionally rename the helper to something
clearer (e.g., profileDisplay) or create a new function for executor mode
display — locate the StatusItem call and change the first argument from "Modo"
to "Perfil" and adjust or rename executorModeDisplay(status.activeProfile) to a
clearer identifier (or implement a separate executorModeDisplay function if you
intend to show executor mode instead).
- Line 62: Status UI shows GPU frequency because StatusScreen uses
status.gpuFreq; add a cpuFreq field to the SystemStatus data model and populate
it in OptimizationEngine.collectStatus() by reading CPU scaling_cur_freq (e.g.
/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq), convert from kHz to MHz,
then update StatusScreen to display status.cpuFreq in the "Frequência"
StatusItem instead of status.gpuFreq. Ensure null/error handling when reading
sysfs and that the value is formatted as an integer/decimal MHz string for the
UI.

In `@app/src/main/java/com/speedcool/app/ui/SpeedCoolNavHost.kt`:
- Around line 107-122: The SettingsScreen call in SpeedCoolNavHost.kt currently
passes hardcoded state and empty callbacks (autoStart, backgroundService,
autoRamClean, learningEnabled, conflictAutoResolve, tempUnit, ramCleanInterval
and
onAutoStartChange/onBackgroundServiceChange/onAutoRamCleanChange/onLearningEnabledChange/onConflictAutoResolveChange/onTempUnitChange/onRamCleanIntervalChange),
so user interactions are no-ops; instead, wire these props to real state and
handlers: obtain or inject a SettingsViewModel (or persistent settings
repository) in SpeedCoolNavHost, replace the hardcoded booleans/values with
ViewModel-backed LiveData/StateFlow values, and implement each callback to call
appropriate ViewModel methods (e.g., settingsViewModel.setAutoStart(enabled),
setBackgroundService(...), setRamCleanInterval(...), setTempUnit(...)) so
changes persist/update UI; ensure SettingsScreen receives current state from the
ViewModel rather than literal literals and that callbacks dispatch updates to
the store.
- Around line 83-91: onStartService/onStopService currently only flip the UI
flag (isServiceRunning) and never start/stop the Android service; update the
handlers in SpeedCoolNavHost so onStartService constructs the service Intent
(targeting your foreground service class), calls
Context.startForegroundService(intent) (or ContextCompat.startForegroundService
if needed), then set isServiceRunning = true and executorMode as done now, and
have onStopService call context.stopService(intent) and set isServiceRunning =
false; locate the anonymous handlers named onStartService and onStopService (and
the usage of scope.launch, isServiceRunning, executorMode, engine.getExecutor())
and inject the startForegroundService/stopService calls using the
Activity/Compose Context available in this scope, handling any returned errors
by logging and only updating UI state after attempting to start/stop the
service.

In `@gradlew`:
- Around line 1-12: The current gradlew script is a minimal custom wrapper (uses
variables like JAVACMD, DIR and directly invokes
org.gradle.wrapper.GradleWrapperMain) and should be replaced with the official
Gradle-generated wrapper that includes Darwin/Cygwin detection, robust arg
parsing and error handling; regenerate and commit the proper wrapper by running
the Gradle wrapper task (e.g., run gradle wrapper --gradle-version 8.5) which
will produce the full gradlew script, gradle/wrapper/gradle-wrapper.jar and
gradle/wrapper/gradle-wrapper.properties to replace the current custom script.

In `@gradlew.bat`:
- Line 1: The gradlew.bat file currently has Unix (LF) line endings which will
break Windows batch parsing; update gradlew.bat to use CRLF line endings so
Windows cmd handles GOTO/CALL labels correctly. Fix by converting the file to
CRLF (e.g., run a unix2dos conversion or change the file's EOL in your editor)
and/or add a .gitattributes rule (e.g., set gradlew.bat to text eol=crlf) or
enable core.autocrlf so future commits preserve CRLF; commit the updated
gradlew.bat with CRLF line endings.

---

Nitpick comments:
In @.github/workflows/android-app.yml:
- Around line 18-19: Remove the error-suppression and output-redirection around
the sdkmanager calls so failures are visible: delete the "|| true" and the ">
/dev/null 2>&1" redirections on the lines invoking sdkmanager, and instead let
the command return a non-zero exit code (or explicitly check its exit status and
exit 1 on failure). Also make the commands robust by adding the SDK root flag
(use --sdk_root="$ANDROID_HOME") to both the license acceptance invocation
(e.g., sdkmanager --licenses) and the package install invocation (sdkmanager
"platforms;android-34" "build-tools;34.0.0"), so the workflow fails loudly if
sdkmanager cannot find or install components.

In @.gradle/buildOutputCleanup/cache.properties:
- Around line 1-2: The repository currently contains the generated Gradle cache
file cache.properties under the .gradle directory which should be excluded from
VCS; update the project's .gitignore to add the entry ".gradle/" and then remove
the tracked .gradle files from the index (e.g., git rm -r --cached .gradle) and
commit the change so the cached build files (cache.properties) are no longer
versioned.

In `@app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt`:
- Around line 135-140: Rename the function executorModeDisplay to
profileDisplayName (or profileDisplay) because it maps Profile enum values, not
ExecutorMode; update the function declaration private fun
executorModeDisplay(profile: Profile): String to the new name (e.g., private fun
profileDisplayName(profile: Profile): String) and change all call sites that
invoke executorModeDisplay(...) (for example the call at the previously noted
call site around line 103) to use the new name so callers compile cleanly; leave
the when mapping of Profile.ECO, Profile.BALANCED, Profile.PERFORMANCE,
Profile.LEARNING unchanged.

In `@gradle/wrapper/gradle-wrapper.properties`:
- Line 3: The Gradle wrapper distributionUrl currently pins Gradle 8.5; validate
compatibility with your Android Gradle Plugin (AGP) and project constraints and
then either keep 8.5 or upgrade the distributionUrl to a vetted newer Gradle
(e.g., 9.5.1) if AGP/project allow; update the distributionUrl entry accordingly
and add a short comment or upgrade note in your repo describing the AGP version
constraint so future reviewers know why you chose 8.5 versus a newer Gradle.

In `@gradlew.bat`:
- Around line 17-92: The current gradlew.bat is a simplified custom wrapper
missing the official Gradle wrapper's robust error handling and path resolution;
replace this file with the official Gradle-generated script by running "gradle
wrapper --gradle-version 8.5" in the project root and committing the generated
gradlew.bat (and associated gradle/wrapper files), ensuring the new script
preserves proper handling around symbols/labels shown in the diff such as
DEFAULT_JVM_OPTS, findJavaFromJavaHome, :execute, :fail and the
CLASSPATH/GradleWrapperMain invocation so you get the battle-tested behavior for
Windows environments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b672db2-1517-40f1-875d-d47b0f0d522e

📥 Commits

Reviewing files that changed from the base of the PR and between fede17c and d4f0391.

⛔ Files ignored due to path filters (8)
  • .gradle/8.5/checksums/checksums.lock is excluded by !**/*.lock
  • .gradle/8.5/checksums/md5-checksums.bin is excluded by !**/*.bin
  • .gradle/8.5/checksums/sha1-checksums.bin is excluded by !**/*.bin
  • .gradle/8.5/dependencies-accessors/dependencies-accessors.lock is excluded by !**/*.lock
  • .gradle/8.5/fileHashes/fileHashes.lock is excluded by !**/*.lock
  • .gradle/buildOutputCleanup/buildOutputCleanup.lock is excluded by !**/*.lock
  • .gradle/buildOutputCleanup/outputFiles.bin is excluded by !**/*.bin
  • gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
📒 Files selected for processing (34)
  • .github/workflows/android-app.yml
  • .gradle/buildOutputCleanup/cache.properties
  • app/build.gradle.kts
  • app/proguard-rules.pro
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/speedcool/app/MainActivity.kt
  • app/src/main/java/com/speedcool/app/SpeedCoolApp.kt
  • app/src/main/java/com/speedcool/app/data/Models.kt
  • app/src/main/java/com/speedcool/app/data/SettingsData.kt
  • app/src/main/java/com/speedcool/app/engine/ConflictDetector.kt
  • app/src/main/java/com/speedcool/app/engine/OptimizationEngine.kt
  • app/src/main/java/com/speedcool/app/engine/PerformanceManager.kt
  • app/src/main/java/com/speedcool/app/engine/RAMManager.kt
  • app/src/main/java/com/speedcool/app/engine/ThermalManager.kt
  • app/src/main/java/com/speedcool/app/root/ShellExecutor.kt
  • app/src/main/java/com/speedcool/app/service/BootReceiver.kt
  • app/src/main/java/com/speedcool/app/service/SpeedCoolService.kt
  • app/src/main/java/com/speedcool/app/ui/SpeedCoolNavHost.kt
  • app/src/main/java/com/speedcool/app/ui/components/Common.kt
  • app/src/main/java/com/speedcool/app/ui/screens/DashboardScreen.kt
  • app/src/main/java/com/speedcool/app/ui/screens/SettingsScreen.kt
  • app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt
  • app/src/main/java/com/speedcool/app/ui/theme/Color.kt
  • app/src/main/java/com/speedcool/app/ui/theme/Theme.kt
  • app/src/main/res/drawable/ic_launcher_foreground.xml
  • app/src/main/res/values/colors.xml
  • app/src/main/res/values/strings.xml
  • app/src/main/res/values/themes.xml
  • build.gradle.kts
  • gradle.properties
  • gradle/wrapper/gradle-wrapper.properties
  • gradlew
  • gradlew.bat
  • settings.gradle.kts

Comment on lines +7 to +11
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What are the latest commit SHAs for actions/checkout v4, actions/setup-java v4, and actions/upload-artifact v4?

💡 Result:

As of May 26, 2026, GitHub Actions tags for version 4 (e.g., v4, v4.1.6, v4.7.1, v7.0.1) are updated over time by the maintainers and point to specific, evolving commits. GitHub Actions are mutable by design when referenced by tags, meaning the commit SHA associated with a version like v4 can change as maintainers push updates to that branch [1]. For security and reproducibility, it is strongly recommended to pin actions to their immutable commit SHAs rather than tags [1][2]. Because the commit SHAs for versioned tags (like v4) are not static and are subject to change by the repository maintainers, they cannot be provided as a single, permanently accurate value [1]. To find the current SHA associated with a specific version tag in your workflow: 1. Navigate to the official repository (e.g., github.com/actions/checkout). 2. Click on the Tags section or the branch/tag dropdown menu. 3. Select the desired tag (e.g., v4). 4. The repository view will update to that tag, and you can see the latest commit SHA associated with it in the file browser or by viewing the commit history [3][4]. For example, referencing actions/checkout@v4 in your workflow will pull the code from whatever commit the maintainers have currently set as the target for that tag [1]. To lock your workflow to a specific, immutable version, you should replace the tag with the full commit SHA, such as: - uses: actions/checkout@ Always consult the official repository release pages for the most recent updates and security information [5][6][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== File: .github/workflows/android-app.yml =="
sed -n '1,120p' .github/workflows/android-app.yml | nl -ba

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 180


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== File: .github/workflows/android-app.yml =="
cat -n .github/workflows/android-app.yml | sed -n '1,200p'

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 1215


🌐 Web query:

actions/checkout v4 persist-credentials default value

💡 Result:

The default value for the persist-credentials input in actions/checkout v4 is true [1][2]. When this setting is enabled (the default), the action configures the local git repository with the authentication token used for the checkout [1][3]. This allows subsequent steps in your workflow to perform authenticated git commands [1][3]. The token is stored in the local git configuration and is removed during the post-job cleanup phase [1][3]. Because the credentials remain available to the job while it is running, it is a recommended security practice to set persist-credentials to false if your workflow does not require authenticated git operations in subsequent steps [4]. This prevents the credential from being exposed to other steps or potentially leaked if the runner environment or artifacts are compromised [5][4]. To disable this behavior, you can explicitly set the input in your workflow YAML: - uses: actions/checkout@v4 with: persist-credentials: false

Citations:


🌐 Web query:

actions/checkout v4.2.2 commit 11bd71901bbe5b1630ceea73d27597364c9af683

💡 Result:

actions/checkout v4.2.2 corresponds to commit 11bd71901bbe5b1630ceea73d27597364c9af683. This commit is part of the v4.2.2 release and includes changes noted in the v4.2.2 changelog: url-helper.ts leveraging well-known environment variables and expanded unit test coverage for isGhes [1][2]. The v4.2.2 release page for actions/checkout was published on 2024-10-23 and links to the v4.2.1...v4.2.2 full changelog comparison [2].

Citations:


🌐 Web query:

actions/setup-java v4.7.1 commit c5195efecf7bdfc987ee8bae7a71cb8b11521c00

💡 Result:

The GitHub Actions actions/setup-java version v4.7.1 is associated with commit c5195efecf7bdfc987ee8bae7a71cb8b11521c00 [1][2]. This version was released on April 9, 2025 [1]. The update primarily focused on documentation improvements and dependency upgrades, including [1][2]: * Documentation: Added recommendations for using GraalVM JDK 17 version 17.0.12 to align with GFTC license terms and removed duplicated GraalVM documentation [1]. * Dependency Updates: Upgraded @actions/cache to 4.0.3, @actions/glob to 0.5.0, and ts-jest to 29.2.5 [1][2].

Citations:


🌐 Web query:

actions/upload-artifact v4.6.2 commit ea165f8d65b6e75b540449e92b4886f43607fa02

💡 Result:

The commit ea165f8d65b6e75b540449e92b4886f43607fa02 corresponds to the version v4.6.2 of the actions/upload-artifact GitHub Action [1][2][3]. Released on March 19, 2025, v4.6.2 included an update to use the artifact 2.3.2 package [1]. As of early 2026, this version is recognized as running on Node.js 20 [4]. Because GitHub Actions migrated support to Node.js 24, workflows using this specific version of the action have triggered deprecation warnings [4][5], as the action platform transitioned away from Node.js 20 in favor of Node.js 24 [5]. Users are advised to upgrade to newer versions (such as v6 or later) which provide native Node.js 24 support [5].

Citations:


Pin GitHub Actions to commit SHAs and disable checkout credential persistence (lines 7-8, 22)

Unpinned @v4 tags are mutable (supply-chain risk). Also, actions/checkout@v4 defaults persist-credentials to true, so set persist-credentials: false if subsequent steps don’t need git auth.

🔒 Proposed fix to pin actions and disable credential persistence
-    - uses: actions/checkout@v4
-    - uses: actions/setup-java@v4
+    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      with:
+        persist-credentials: false
+    - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
       with:
         java-version: '17'
         distribution: 'temurin'

And for upload-artifact:

-    - uses: actions/upload-artifact@v4
+    - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with:
java-version: '17'
distribution: 'temurin'
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 7-7: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 7-7: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 8-8: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/android-app.yml around lines 7 - 11, Pin the reusable
GitHub Actions and disable credential persistence: replace mutable tags like
actions/checkout@v4 and actions/setup-java@v4 with their pinned commit SHAs (use
the specific commit SHA for actions/checkout and actions/setup-java) and add
persist-credentials: false under the actions/checkout step to prevent leaking
git auth; also pin any other actions used (e.g., actions/upload-artifact) to
their SHAs to eliminate supply-chain risk.

Comment thread app/proguard-rules.pro
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether the app really performs package installation.
# Expected: if no relevant matches are found, remove Line 9 permission.

rg -n -C2 --type=kt 'PackageInstaller|ACTION_INSTALL_PACKAGE|application/vnd\.android\.package-archive|Intent\.ACTION_VIEW|SessionParams|REQUEST_INSTALL_PACKAGES'
rg -n -C2 --type=xml 'REQUEST_INSTALL_PACKAGES|ACTION_INSTALL_PACKAGE|package-archive'

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 683


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for install-related APIs/intents/URI types that would justify REQUEST_INSTALL_PACKAGES
rg -n --hidden --no-ignore-vcs \
  'PackageInstaller|ACTION_INSTALL_PACKAGE|ACTION_VIEW|package-archive|application/vnd\.android\.package-archive|SessionParams|REQUEST_INSTALL_PACKAGES' .

# Narrow to code-level install intents (commonly for sideload/install flows)
rg -n --hidden --no-ignore-vcs \
  'Intent\.ACTION_(VIEW|INSTALL)|putExtra\(|setDataAndType\(|application/vnd\.android\.package-archive' .

# Also check for any mention of "install packages" user flows / UI strings
rg -n --hidden --no-ignore-vcs \
  'install (package|apk|application)|sideload' .

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 193


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for hardcoded label(s) in the manifest
rg -n --hidden --no-ignore-vcs 'android:label\s*=' app/src/main/AndroidManifest.xml

# Broader search for any install/sideload UI/actions that might not match earlier keyword set
rg -n --hidden --no-ignore-vcs \
  'install (package|packages)|sideload|APK|package-archive|REQUEST_INSTALL_PACKAGES|PackageInstaller|ACTION_INSTALL_PACKAGE|ACTION_VIEW.*(apk|package|archive)' \
  app/src/main . || true

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 348


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --no-ignore-vcs \
  'REQUEST_INSTALL_PACKAGES|android\.permission\.REQUEST_INSTALL_PACKAGES|PackageInstaller|ACTION_INSTALL_PACKAGE|ACTION_VIEW|package-archive|application/vnd\.android\.package-archive|SessionParams' . || true

rg -n --hidden --no-ignore-vcs \
  'startActivity.*(apk|package-archive|install)|setDataAndType\(|FLAG_GRANT_READ_URI_PERMISSION|android\.net\.Uri|content://.*\.apk|FileProvider.*\.apk' . || true

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 193


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find any string resource for app name/SpeedCool
rg -n --hidden --no-ignore-vcs 'SpeedCool' app/src/main/res || true
rg -n --hidden --no-ignore-vcs 'name\s*=\s*".*SpeedCool|app_name' app/src/main/res/values || true

# See if manifest label uses a `@string` reference anywhere else
rg -n --hidden --no-ignore-vcs 'android:label\s*=\s*"`@string/`' app/src/main/AndroidManifest.xml || true

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 725


Remove REQUEST_INSTALL_PACKAGES unless the app truly installs APKs

  • android.permission.REQUEST_INSTALL_PACKAGES is present only in app/src/main/AndroidManifest.xml, with no repo references to install flows (PackageInstaller, ACTION_INSTALL_PACKAGE, package-archive, or related install intents).
  • app/src/main/AndroidManifest.xml hardcodes android:label="SpeedCool" even though app/src/main/res/values/strings.xml provides @string/app_name; use the string resource for localization.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/AndroidManifest.xml` at line 9, Remove the unnecessary
uses-permission entry for android.permission.REQUEST_INSTALL_PACKAGES from the
manifest (no PackageInstaller/ACTION_INSTALL_PACKAGE usage in the codebase);
also replace the hardcoded android:label="SpeedCool" attribute with the string
resource reference android:label="`@string/app_name`" so the app uses the
localized value from res/values/strings.xml.

android:allowBackup="true"
android:icon="@drawable/ic_launcher_foreground"
android:roundIcon="@drawable/ic_launcher_foreground"
android:label="SpeedCool"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a string resource for the app label.

android:label="SpeedCool" should reference @string/app_name to support localization and consistent branding.

💡 Suggested change
-        android:label="SpeedCool"
+        android:label="`@string/app_name`"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
android:label="SpeedCool"
android:label="`@string/app_name`"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/AndroidManifest.xml` at line 18, Replace the hard-coded app
label "SpeedCool" in the Android manifest with a string resource reference:
update the android:label attribute (in AndroidManifest.xml) to use
`@string/app_name` and ensure the app_name entry exists in res/values/strings.xml;
if missing, add app_name="SpeedCool" (or localized values) to strings.xml so the
manifest references a resource rather than a literal.

Comment on lines +54 to +66
val settingsFlow: Flow<Settings> = context.dataStore.data.map { prefs ->
Settings(
executorMode = prefs[KEY_EXECUTOR_MODE] ?: DEFAULT.executorMode,
activeProfile = prefs[KEY_ACTIVE_PROFILE] ?: DEFAULT.activeProfile,
autoStart = prefs[KEY_AUTO_START] ?: DEFAULT.autoStart,
backgroundService = prefs[KEY_BACKGROUND_SERVICE] ?: DEFAULT.backgroundService,
autoRamClean = prefs[KEY_AUTO_RAM_CLEAN] ?: DEFAULT.autoRamClean,
tempUnit = prefs[KEY_TEMP_UNIT] ?: DEFAULT.tempUnit,
ramCleanInterval = prefs[KEY_RAM_CLEAN_INTERVAL] ?: DEFAULT.ramCleanInterval,
learningEnabled = prefs[KEY_LEARNING_ENABLED] ?: DEFAULT.learningEnabled,
conflictAutoResolve = prefs[KEY_CONFLICT_AUTO_RESOLVE] ?: DEFAULT.conflictAutoResolve
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the target file (and print relevant lines around the snippet)
FILE="app/src/main/java/com/speedcool/app/data/SettingsData.kt"
test -f "$FILE" || { echo "Missing: $FILE"; exit 1; }

echo "== Snippet around settingsFlow =="
nl -ba "$FILE" | sed -n '40,90p'

# Find where `dataStore` is defined for `context` and whether exceptions are handled already
echo
echo "== Search for dataStore delegate/definition =="
rg -n "preferencesDataStore|DataStore<Preferences>|dataStore\s*=" app/src/main/java || true

echo
echo "== Search for catch/exception handling around context.dataStore.data usage =="
rg -n "context\.dataStore\.data|\.data\s*\n\s*\.catch|\.data\s*\n\s*catch|flow.*catch" app/src/main/java || true

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 168


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="app/src/main/java/com/speedcool/app/data/SettingsData.kt"
test -f "$FILE" || { echo "Missing: $FILE"; exit 1; }

echo "== settingsFlow snippet (lines 45-75) =="
sed -n '45,75p' "$FILE" | cat -n

echo
echo "== Exact lines containing settingsFlow =="
rg -n "settingsFlow" "$FILE" || true

echo
echo "== dataStore definitions / delegates =="
rg -n "preferencesDataStore|DataStore<Preferences>|dataStore\s*=" app/src/main/java || true

echo
echo "== Any exception handling near context.dataStore.data =="
rg -n "context\.dataStore\.data|\.data\s*\{|\.(catch|retry)|IOException|emptyPreferences" app/src/main/java || true

echo
echo "== Search for SettingsData.kt dataStore field/context setup =="
rg -n "class SettingsData|object SettingsData|SettingsData" "$FILE" || true

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 2564


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="app/src/main/java/com/speedcool/app/data/SettingsData.kt"
test -f "$FILE" || { echo "Missing: $FILE"; exit 1; }

echo "== Top of SettingsData.kt =="
sed -n '1,120p' "$FILE" | cat -n

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 4951


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="app/src/main/java/com/speedcool/app/data/SettingsData.kt"
test -f "$FILE" || { echo "Missing: $FILE"; exit 1; }

echo "== Top of SettingsData.kt =="
sed -n '1,120p' "$FILE" | cat -n

Repository: Llucs/SpeedCool-Magisk-Module

Length of output: 4951


🌐 Web query:

AndroidX DataStore Preferences data flow throws IOException corruptionHandler catch behavior

💡 Result:

In AndroidX DataStore, an IOException resulting from file corruption is typically wrapped as a CorruptionException [1]. DataStore does not automatically recover from this state; without a configured corruption handler, attempts to read from the corrupted file will propagate the exception [2]. To handle this gracefully, you must provide a corruptionHandler when creating your DataStore instance [2]. The handler is specifically designed to intercept the CorruptionException during read attempts [3][4][5]. Behavior of the CorruptionHandler: 1. If corruption is detected, the handler's handleCorruption method is invoked with the caught CorruptionException [1]. 2. The implementation of this method must return a default object (e.g., empty Preferences) that DataStore will attempt to write to disk, effectively resetting the file [1][2]. 3. If your handler implementation throws an exception, that exception will propagate and be thrown to the original caller [1]. 4. The handler must not interact with any DataStore API, as doing so can result in a deadlock [1]. Common implementation: Most developers use the ReplaceFileCorruptionHandler, which simply replaces the corrupted file with a fresh, empty state [6][2]. Example setup: val dataStore = PreferenceDataStoreFactory.create( corruptionHandler = ReplaceFileCorruptionHandler { emptyPreferences }, produceFile = { context.preferencesDataStoreFile("my_data") }) Note that if you catch IOException manually in your repository or collect block, ensure you correctly handle coroutine cancellation [7]. Avoid swallowing CancellationException in generic catch blocks, as this can break structured concurrency and lead to inconsistent app states [7].

Citations:


🌐 Web query:

preferencesDataStore(...) corruptionHandler ReplaceFileCorruptionHandler parameter availability Kotlin AndroidX DataStore

💡 Result:

Yes, the corruptionHandler parameter using ReplaceFileCorruptionHandler is available and supported in the preferencesDataStore delegate for AndroidX DataStore [1][2]. The preferencesDataStore property delegate allows you to configure a corruption handler to gracefully manage cases where DataStore encounters a CorruptionException (typically when data cannot be deserialized) [1][2]. You can provide a ReplaceFileCorruptionHandler, which attempts to replace the corrupted file with new, valid data generated by a provided callback [3][4]. Example usage: val Context.dataStore by preferencesDataStore( name = "settings", corruptionHandler = ReplaceFileCorruptionHandler { // Return default preferences to replace the corrupted file emptyPreferences }) When configured, if DataStore detects corruption during a read, it will invoke the handler's produceNewData callback and attempt to overwrite the corrupted file with the returned data, avoiding an application crash [5][4]. If no handler is provided, a CorruptionException will be thrown when corruption is encountered [5].

Citations:


Handle DataStore corruption/read failures for settingsFlow

At line 54, context.dataStore.data is mapped directly. If the on-disk preferences are corrupted (typically surfaced as CorruptionException), the settingsFlow collector can fail because the preferencesDataStore delegate has no corruptionHandler.

💡 Proposed fix
 package com.speedcool.app.data
 
 import android.content.Context
 import androidx.datastore.core.DataStore
+import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
 import androidx.datastore.preferences.core.Preferences
 import androidx.datastore.preferences.core.booleanPreferencesKey
+import androidx.datastore.preferences.core.emptyPreferences
 import androidx.datastore.preferences.core.edit
 import androidx.datastore.preferences.core.intPreferencesKey
 import androidx.datastore.preferences.core.stringPreferencesKey
 import androidx.datastore.preferences.preferencesDataStore
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.map
 
-private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "speedcool_settings")
+private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
+    name = "speedcool_settings",
+    corruptionHandler = ReplaceFileCorruptionHandler { emptyPreferences() }
+)
 
 class SettingsData(private val context: Context) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/data/SettingsData.kt` around lines 54 -
66, The settingsFlow currently maps context.dataStore.data directly and will
crash on DataStore corruption; wrap the upstream flow with a catch that converts
CorruptionException into a safe fallback (e.g., emit(emptyPreferences())) before
the map so the collector won't fail. Concretely, update settingsFlow to use
context.dataStore.data.catch { e -> if (e is CorruptionException) { /* log */
emit(emptyPreferences()) } else throw e } . Then keep the existing .map { prefs
-> Settings(...) } unchanged; reference symbols: settingsFlow,
context.dataStore.data, CorruptionException, emptyPreferences().


StatusSection("Dispositivo") {
StatusItem("Chipset", status.chipset)
StatusItem("Modo", executorModeDisplay(status.activeProfile))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify what "Modo" represents.

The label "Modo" (Mode) combined with the function name executorModeDisplay suggests this field displays the executor mode (Root vs. Shizuku). However, the function actually displays the performance profile (Eco/Balanced/Performance/Learning). This naming is potentially confusing.

Consider either:

  • Change the label to "Perfil" (Profile) to match what's actually displayed
  • Or if executor mode should be shown here, implement a separate function to display it
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/ui/screens/StatusScreen.kt` at line 103,
The UI label "Modo" is misleading because StatusItem("Modo",
executorModeDisplay(status.activeProfile)) actually shows the performance
profile (status.activeProfile) not the executor mode; update the label to
"Perfil" to match the data, and optionally rename the helper to something
clearer (e.g., profileDisplay) or create a new function for executor mode
display — locate the StatusItem call and change the first argument from "Modo"
to "Perfil" and adjust or rename executorModeDisplay(status.activeProfile) to a
clearer identifier (or implement a separate executorModeDisplay function if you
intend to show executor mode instead).

Comment on lines +83 to +91
onStartService = {
scope.launch {
isServiceRunning = true
executorMode = engine.getExecutor()?.mode ?: "none"
}
},
onStopService = {
isServiceRunning = false
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Start/stop actions do not control the Android service.

onStartService / onStopService only mutate local UI state (isServiceRunning) and never call Context.startForegroundService(...) / stopService(...), so the control button can report running while nothing is actually running.

Proposed fix
+import android.content.Context
+import android.content.Intent
+import androidx.compose.ui.platform.LocalContext
+import com.speedcool.app.service.SpeedCoolService
@@
 fun SpeedCoolNavHost() {
+    val context = LocalContext.current
@@
                     onStartService = {
                         scope.launch {
-                            isServiceRunning = true
+                            context.startForegroundService(Intent(context, SpeedCoolService::class.java))
+                            isServiceRunning = true
                             executorMode = engine.getExecutor()?.mode ?: "none"
                         }
                     },
                     onStopService = {
+                        context.stopService(Intent(context, SpeedCoolService::class.java))
                         isServiceRunning = false
                     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onStartService = {
scope.launch {
isServiceRunning = true
executorMode = engine.getExecutor()?.mode ?: "none"
}
},
onStopService = {
isServiceRunning = false
},
onStartService = {
scope.launch {
context.startForegroundService(Intent(context, SpeedCoolService::class.java))
isServiceRunning = true
executorMode = engine.getExecutor()?.mode ?: "none"
}
},
onStopService = {
context.stopService(Intent(context, SpeedCoolService::class.java))
isServiceRunning = false
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/ui/SpeedCoolNavHost.kt` around lines 83 -
91, onStartService/onStopService currently only flip the UI flag
(isServiceRunning) and never start/stop the Android service; update the handlers
in SpeedCoolNavHost so onStartService constructs the service Intent (targeting
your foreground service class), calls Context.startForegroundService(intent) (or
ContextCompat.startForegroundService if needed), then set isServiceRunning =
true and executorMode as done now, and have onStopService call
context.stopService(intent) and set isServiceRunning = false; locate the
anonymous handlers named onStartService and onStopService (and the usage of
scope.launch, isServiceRunning, executorMode, engine.getExecutor()) and inject
the startForegroundService/stopService calls using the Activity/Compose Context
available in this scope, handling any returned errors by logging and only
updating UI state after attempting to start/stop the service.

Comment on lines +107 to +122
Screen.Settings -> SettingsScreen(
autoStart = false,
backgroundService = true,
autoRamClean = true,
learningEnabled = true,
conflictAutoResolve = true,
tempUnit = "celsius",
ramCleanInterval = 180,
onAutoStartChange = {},
onBackgroundServiceChange = {},
onAutoRamCleanChange = {},
onLearningEnabledChange = {},
onConflictAutoResolveChange = {},
onTempUnitChange = {},
onRamCleanIntervalChange = {}
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Settings are wired as no-ops.

All settings callbacks are empty, so the screen appears interactive but cannot change app configuration/state.

Proposed fix direction
-                Screen.Settings -> SettingsScreen(
-                    autoStart = false,
-                    backgroundService = true,
-                    autoRamClean = true,
-                    learningEnabled = true,
-                    conflictAutoResolve = true,
-                    tempUnit = "celsius",
-                    ramCleanInterval = 180,
-                    onAutoStartChange = {},
-                    onBackgroundServiceChange = {},
-                    onAutoRamCleanChange = {},
-                    onLearningEnabledChange = {},
-                    onConflictAutoResolveChange = {},
-                    onTempUnitChange = {},
-                    onRamCleanIntervalChange = {}
-                )
+                Screen.Settings -> SettingsScreen(
+                    autoStart = autoStart,
+                    backgroundService = backgroundService,
+                    autoRamClean = autoRamClean,
+                    learningEnabled = learningEnabled,
+                    conflictAutoResolve = conflictAutoResolve,
+                    tempUnit = tempUnit,
+                    ramCleanInterval = ramCleanInterval,
+                    onAutoStartChange = { autoStart = it },
+                    onBackgroundServiceChange = { backgroundService = it },
+                    onAutoRamCleanChange = { autoRamClean = it },
+                    onLearningEnabledChange = { learningEnabled = it },
+                    onConflictAutoResolveChange = { conflictAutoResolve = it },
+                    onTempUnitChange = { tempUnit = it },
+                    onRamCleanIntervalChange = { ramCleanInterval = it }
+                )

(Back these states with persistent settings store as next step.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/ui/SpeedCoolNavHost.kt` around lines 107
- 122, The SettingsScreen call in SpeedCoolNavHost.kt currently passes hardcoded
state and empty callbacks (autoStart, backgroundService, autoRamClean,
learningEnabled, conflictAutoResolve, tempUnit, ramCleanInterval and
onAutoStartChange/onBackgroundServiceChange/onAutoRamCleanChange/onLearningEnabledChange/onConflictAutoResolveChange/onTempUnitChange/onRamCleanIntervalChange),
so user interactions are no-ops; instead, wire these props to real state and
handlers: obtain or inject a SettingsViewModel (or persistent settings
repository) in SpeedCoolNavHost, replace the hardcoded booleans/values with
ViewModel-backed LiveData/StateFlow values, and implement each callback to call
appropriate ViewModel methods (e.g., settingsViewModel.setAutoStart(enabled),
setBackgroundService(...), setRamCleanInterval(...), setTempUnit(...)) so
changes persist/update UI; ensure SettingsScreen receives current state from the
ViewModel rather than literal literals and that callbacks dispatch updates to
the store.

Comment thread gradlew
Comment on lines +1 to +12
#!/bin/sh
# Gradle wrapper script
if [ -n "$JAVA_HOME" ]; then
JAVACMD="$JAVA_HOME/bin/java"
else
JAVACMD=java
fi
DIR=$(dirname "$0")
exec "$JAVACMD" \
-Dorg.gradle.appname=gradlew \
-classpath "$DIR/gradle/wrapper/gradle-wrapper.jar" \
org.gradle.wrapper.GradleWrapperMain "$@"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use the official Gradle wrapper script.

This is a minimal custom wrapper script instead of the standard Gradle-generated gradlew. The official wrapper includes additional features like Darwin/Cygwin detection, proper argument parsing, Gradle project location resolution, and better error handling. Using the official wrapper ensures consistency and maintainability.

Generate the official wrapper by running:

gradle wrapper --gradle-version 8.5
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gradlew` around lines 1 - 12, The current gradlew script is a minimal custom
wrapper (uses variables like JAVACMD, DIR and directly invokes
org.gradle.wrapper.GradleWrapperMain) and should be replaced with the official
Gradle-generated wrapper that includes Darwin/Cygwin detection, robust arg
parsing and error handling; regenerate and commit the proper wrapper by running
the Gradle wrapper task (e.g., run gradle wrapper --gradle-version 8.5) which
will produce the full gradlew script, gradle/wrapper/gradle-wrapper.jar and
gradle/wrapper/gradle-wrapper.properties to replace the current custom script.

Comment thread gradlew.bat
@@ -0,0 +1,92 @@
@rem

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix Unix line endings in Windows batch file.

The batch file uses Unix line endings (LF) instead of Windows line endings (CRLF), which will cause script failures on Windows due to batch parser bugs with GOTO/CALL label parsing. This will break builds on Windows systems.

Convert the file to CRLF line endings:

#!/bin/bash
# Convert gradlew.bat to Windows line endings
unix2dos gradlew.bat
# Or configure git to handle line endings automatically
git config core.autocrlf true
🧰 Tools
🪛 Blinter (1.0.112)

[error] 1-1: Unix line endings detected. Explanation: Batch file uses Unix line endings (LF-only) which can cause GOTO/CALL label parsing failures and script malfunction due to Windows batch parser 512-byte boundary bugs. Recommendation: Convert file to Windows line endings (CRLF). Use tools like dos2unix, notepad++, or configure git with 'git config core.autocrlf true'. Context: File uses Unix line endings (LF-only) - 92 LF sequences found

(E018)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gradlew.bat` at line 1, The gradlew.bat file currently has Unix (LF) line
endings which will break Windows batch parsing; update gradlew.bat to use CRLF
line endings so Windows cmd handles GOTO/CALL labels correctly. Fix by
converting the file to CRLF (e.g., run a unix2dos conversion or change the
file's EOL in your editor) and/or add a .gitattributes rule (e.g., set
gradlew.bat to text eol=crlf) or enable core.autocrlf so future commits preserve
CRLF; commit the updated gradlew.bat with CRLF line endings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/src/main/java/com/speedcool/app/root/ShellExecutor.kt (2)

18-29: 💤 Low value

Process and stream resources may leak on exception.

If an exception occurs after starting the process but before waitFor(), the process and its streams are not explicitly closed. Consider wrapping in process.use {} or a try-finally with process.destroy().

Additionally, reading inputStream fully before errorStream can deadlock if stderr fills its buffer first (uncommon for small outputs, but possible for verbose errors).

♻️ Safer pattern using concurrent stream consumption
 override suspend fun execute(command: String): Result<String> = withContext(Dispatchers.IO) {
     try {
         val process = Runtime.getRuntime().exec(arrayOf("su", "-c", command))
-        val output = process.inputStream.bufferedReader().readText().trim()
-        val error = process.errorStream.bufferedReader().readText().trim()
-        val exitCode = process.waitFor()
-        if (exitCode == 0) Result.success(output)
-        else Result.failure(RuntimeException("Exit $exitCode: $error"))
+        try {
+            val output = process.inputStream.bufferedReader().readText().trim()
+            val error = process.errorStream.bufferedReader().readText().trim()
+            val exitCode = process.waitFor()
+            if (exitCode == 0) Result.success(output)
+            else Result.failure(RuntimeException("Exit $exitCode: $error"))
+        } finally {
+            process.destroy()
+        }
     } catch (e: Exception) {
         Result.failure(e)
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/root/ShellExecutor.kt` around lines 18 -
29, In ShellExecutor.execute, the started Process and its streams (process,
inputStream, errorStream) can leak or deadlock; change the implementation to
ensure the Process is closed in all cases (e.g., use process.use { } or a
try/finally that calls process.destroy() and closes streams) and read stdout and
stderr concurrently (e.g., launch two coroutines or threads to read
process.inputStream and process.errorStream into variables) before calling
process.waitFor(), then return Result.success or Result.failure based on
exitCode; make these changes inside the execute function to guarantee no
resource leaks and avoid blocking on one stream.

128-128: 💤 Low value

Hardcoded Portuguese string in error message.

The error message should use a string resource or English for consistency and maintainability across the codebase.

✏️ Suggested change
-            throw RuntimeException("Nenhum método de execução disponível")
+            throw RuntimeException("No execution method available")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/speedcool/app/root/ShellExecutor.kt` at line 128, In
ShellExecutor (locate the throw RuntimeException in ShellExecutor.kt), replace
the hardcoded Portuguese message with a localizable string: either throw a
RuntimeException using context.getString(R.string.no_execution_method_available)
(and add a strings.xml entry named no_execution_method_available with an English
value "No execution method available") or, if you prefer immediate fix, replace
the literal with the English text "No execution method available"; ensure you
update callers/construction to have access to a Context if you switch to
getString.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/android-app.yml:
- Around line 2-5: The workflow trigger currently only runs for branch
"app-v2.4" (on: push: branches: [ "app-v2.4" ]) which will skip CI on main after
merges; update the workflow triggers to include "main" and/or pull_request
targets so CI runs for merges and PRs (e.g., add "main" to the push branches
array and add a pull_request trigger) to ensure the pipeline protects main and
PRs.

---

Nitpick comments:
In `@app/src/main/java/com/speedcool/app/root/ShellExecutor.kt`:
- Around line 18-29: In ShellExecutor.execute, the started Process and its
streams (process, inputStream, errorStream) can leak or deadlock; change the
implementation to ensure the Process is closed in all cases (e.g., use
process.use { } or a try/finally that calls process.destroy() and closes
streams) and read stdout and stderr concurrently (e.g., launch two coroutines or
threads to read process.inputStream and process.errorStream into variables)
before calling process.waitFor(), then return Result.success or Result.failure
based on exitCode; make these changes inside the execute function to guarantee
no resource leaks and avoid blocking on one stream.
- Line 128: In ShellExecutor (locate the throw RuntimeException in
ShellExecutor.kt), replace the hardcoded Portuguese message with a localizable
string: either throw a RuntimeException using
context.getString(R.string.no_execution_method_available) (and add a strings.xml
entry named no_execution_method_available with an English value "No execution
method available") or, if you prefer immediate fix, replace the literal with the
English text "No execution method available"; ensure you update
callers/construction to have access to a Context if you switch to getString.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7731e3c5-5349-43ae-b46f-dd4b8bf15c0b

📥 Commits

Reviewing files that changed from the base of the PR and between d4f0391 and bb2c93f.

⛔ Files ignored due to path filters (1)
  • gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
📒 Files selected for processing (9)
  • .github/workflows/android-app.yml
  • .gitignore
  • app/README.md
  • app/build.gradle.kts
  • app/proguard-rules.pro
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/speedcool/app/root/ShellExecutor.kt
  • app/src/main/java/com/speedcool/app/service/BootReceiver.kt
  • app/src/main/java/com/speedcool/app/service/SpeedCoolService.kt
✅ Files skipped from review due to trivial changes (1)
  • app/README.md

Comment on lines 2 to +5
on:
workflow_dispatch:

concurrency:
group: speedcool-app-${{ github.ref }}
cancel-in-progress: true

push:
branches: [ "app-v2.4" ]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Workflow trigger is scoped to app-v2.4, so CI may stop on main after merge.

If this workflow is meant to protect the mainline, add main (and usually PRs targeting main) to triggers.

Suggested minimal update
 on:
   workflow_dispatch:
+  pull_request:
+    branches: [ "main" ]
   push:
-    branches: [ "app-v2.4" ]
+    branches: [ "main", "app-v2.4" ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
workflow_dispatch:
concurrency:
group: speedcool-app-${{ github.ref }}
cancel-in-progress: true
push:
branches: [ "app-v2.4" ]
on:
workflow_dispatch:
pull_request:
branches: [ "main" ]
push:
branches: [ "main", "app-v2.4" ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/android-app.yml around lines 2 - 5, The workflow trigger
currently only runs for branch "app-v2.4" (on: push: branches: [ "app-v2.4" ])
which will skip CI on main after merges; update the workflow triggers to include
"main" and/or pull_request targets so CI runs for merges and PRs (e.g., add
"main" to the push branches array and add a pull_request trigger) to ensure the
pipeline protects main and PRs.

This branch has not been deployed

No deployments
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant