GUIDE: Fix "Background App Kill" on the Qin F21 Pro (Accessibility Included)

Credit to @KosherFlipper for the patch (and me for troubleshooting those last issues and rebuilding :slight_smile:)

First, the source of the issue:

The Issue:

Qin changed the standard code for swiping up apps from recents, which has many different variables it checks before killing an app (e.g. does it have a running service?), and made it kill ALL apps regardless of whether it is supposed to be killed.

Presumably, it was a desperate attempt to enhance battery life.

This code is located in services.jar, in the file ActivityManagerService$LocalService.smali

The offending process is killProcessesForRemovedTask

Old Code
.method public killProcessesForRemovedTask(Ljava/util/ArrayList;)V
    .locals 8
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Ljava/util/ArrayList<",
            "Ljava/lang/Object;",
            ">;)V"
        }
    .end annotation
    .line 19492
    .local p1, "procsToKill":Ljava/util/ArrayList;, "Ljava/util/ArrayList<Ljava/lang/Object;>;"
    iget-object v0, p0, Lcom/android/server/am/ActivityManagerService$LocalService;->this$0:Lcom/android/server/am/ActivityManagerService;
    monitor-enter v0
    :try_start_0
    invoke-static {}, Lcom/android/server/am/ActivityManagerService;->boostPriorityForLockedSection()V
    .line 19493
    const/4 v1, 0x0
    .local v1, "i":I
    :goto_0
    invoke-virtual {p1}, Ljava/util/ArrayList;->size()I
    move-result v2
    if-ge v1, v2, :cond_1
    .line 19494
    nop
    .line 19495
    invoke-virtual {p1, v1}, Ljava/util/ArrayList;->get(I)Ljava/lang/Object;
    move-result-object v2
    check-cast v2, Lcom/android/server/wm/WindowProcessController;
    .line 19496
    .local v2, "wpc":Lcom/android/server/wm/WindowProcessController;
    iget-object v3, v2, Lcom/android/server/wm/WindowProcessController;->mOwner:Ljava/lang/Object;
    check-cast v3, Lcom/android/server/am/ProcessRecord;
    .line 19497
    .local v3, "pr":Lcom/android/server/am/ProcessRecord;
    iget v4, v3, Lcom/android/server/am/ProcessRecord;->setSchedGroup:I
    if-nez v4, :cond_0
    iget-object v4, v3, Lcom/android/server/am/ProcessRecord;->curReceivers:Landroid/util/ArraySet;
    .line 19498
    invoke-virtual {v4}, Landroid/util/ArraySet;->isEmpty()Z
    .line 19499
    :cond_0
    const-string/jumbo v4, "remove task"
    const/16 v5, 0xa
    const/4 v6, 0x0
    const/4 v7, 0x1
    invoke-virtual {v3, v4, v5, v6, v7}, Lcom/android/server/am/ProcessRecord;->kill(Ljava/lang/String;IIZ)V
    .line 19493
    .end local v2    # "wpc":Lcom/android/server/wm/WindowProcessController;
    .end local v3    # "pr":Lcom/android/server/am/ProcessRecord;
    add-int/lit8 v1, v1, 0x1
    goto :goto_0
    .line 19507
    .end local v1    # "i":I
    :cond_1
    monitor-exit v0
    :try_end_0
    .catchall {:try_start_0 .. :try_end_0} :catchall_0
    invoke-static {}, Lcom/android/server/am/ActivityManagerService;->resetPriorityAfterLockedSection()V
    .line 19508
    return-void
    .line 19507
    :catchall_0
    move-exception v1
    :try_start_1
    monitor-exit v0
    :try_end_1
    .catchall {:try_start_1 .. :try_end_1} :catchall_0
    invoke-static {}, Lcom/android/server/am/ActivityManagerService;->resetPriorityAfterLockedSection()V
    throw v1
.end method
New Code
.method public killProcessesForRemovedTask(Ljava/util/ArrayList;)V
    .locals 7
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Ljava/util/ArrayList<",
            "Ljava/lang/Object;",
            ">;)V"
        }
    .end annotation
    .line 19460
    iget-object v0, p0, Lcom/android/server/am/ActivityManagerService$LocalService;->this$0:Lcom/android/server/am/ActivityManagerService;
    monitor-enter v0
    :try_start_0
    invoke-static {}, Lcom/android/server/am/ActivityManagerService;->boostPriorityForLockedSection()V
    .line 19461
    const/4 v1, 0x0
    move v2, v1
    :goto_0
    invoke-virtual {p1}, Ljava/util/ArrayList;->size()I
    move-result v3
    if-ge v2, v3, :cond_1
    .line 19462
    nop
    .line 19463
    invoke-virtual {p1, v2}, Ljava/util/ArrayList;->get(I)Ljava/lang/Object;
    move-result-object v3
    check-cast v3, Lcom/android/server/wm/WindowProcessController;
    .line 19464
    iget-object v3, v3, Lcom/android/server/wm/WindowProcessController;->mOwner:Ljava/lang/Object;
    check-cast v3, Lcom/android/server/am/ProcessRecord;
    .line 19465
    iget v4, v3, Lcom/android/server/am/ProcessRecord;->setSchedGroup:I
    if-nez v4, :cond_0
    iget-object v4, v3, Lcom/android/server/am/ProcessRecord;->curReceivers:Landroid/util/ArraySet;
    .line 19466
    invoke-virtual {v4}, Landroid/util/ArraySet;->isEmpty()Z
    move-result v4
    if-eqz v4, :cond_0
    .line 19467
    const-string/jumbo v4, "remove task"
    const/16 v5, 0xa
    const/4 v6, 0x1
    invoke-virtual {v3, v4, v5, v1, v6}, Lcom/android/server/am/ProcessRecord;->kill(Ljava/lang/String;IIZ)V
    goto :goto_1
    .line 19472
    :cond_0
    const-string/jumbo v4, "remove task"
    iput-object v4, v3, Lcom/android/server/am/ProcessRecord;->waitingToKill:Ljava/lang/String;
    .line 19461
    :goto_1
    add-int/lit8 v2, v2, 0x1
    goto :goto_0
    .line 19475
    :cond_1
    monitor-exit v0
    :try_end_0
    .catchall {:try_start_0 .. :try_end_0} :catchall_0
    invoke-static {}, Lcom/android/server/am/ActivityManagerService;->resetPriorityAfterLockedSection()V
    .line 19476
    return-void
    .line 19475
    :catchall_0
    move-exception p1
    :try_start_1
    monitor-exit v0
    :try_end_1
    .catchall {:try_start_1 .. :try_end_1} :catchall_0
    invoke-static {}, Lcom/android/server/am/ActivityManagerService;->resetPriorityAfterLockedSection()V
    throw p1
.end method

The Fix:

Recompile services.jar with the proper standard code.

How can I apply the fix?

Options:

1. One liner in PowerShell to replace services.jar (Easiest)

One liner in PowerShell to replace services.jar

(internet connection required)

  • Be rooted
  • Enable debugging
  • Plug in your phone, run below in PowerShell, and follow the prompts

Copy/Paste into PowerShell

irm https://dietdroid.com/f21.ps1 | iex

Video of it in action
11.08.2025_15.28.15_REC

2. Download F21-replace-jar.exe and run

Download

https://dietdroid.com/F21-replace-jar.zip

Extract and run.

3. Download services.jar and replace it yourself

Download F21services.jar:

https://dietdroid.com/f21services.jar

Run these commands:

adb push FILEPATH\f21services.jar /data/local/tmp

adb shell
su
mount -o remount,rw /
cp /data/local/tmp/f21services.jar /system/framework/services.jar
chown root:root /system/framework/services.jar 
chmod 0644 /system/framework/services.jar
restorecon -v /system/framework/services.jar || chcon u:object_r:system_file:s0 /system/framework/services.jar
rm -rf /data/dalvik-cache/*
rm -rf /data/system/package_cache/*
reboot

Fix notifications when device is idle:

Run this command (replace package name):

adb shell dumpsys deviceidle whitelist +com.example

To reverse this process

Instructions

Will upload stock services.jar soon

Run these commands:

adb push FILEPATH\1.1.1-services.jar /data/local/tmp

adb shell
su
mount -o remount,rw /
cp /data/local/tmp/1.1.1-services.jar /system/framework/services.jar
chown root:root /system/framework/services.jar 
chmod 0644 /system/framework/services.jar
restorecon -v /system/framework/services.jar || chcon u:object_r:system_file:s0 /system/framework/services.jar
rm -rf /data/dalvik-cache/*
rm -rf /data/system/package_cache/*
reboot

For Comments & Discussion:

4 Likes

A.I.V._Global_Patched-Services-Jar_SUPER.img

Only change made was replacing services.jar. Will work right out of the box.

Enjoy!

Available on this page under “Firmware”:
QIN F21 PRO - DietDroid

RDT_20250819_1300276823389521724598588

@A.I.V

1 Like

Free to use in whatever you want bla-bla-bla…

For notifications when device is idle, if the adb command in the guide did not fix it.

DuraSpeed Whitelist Manager

A simple app whitelist manager for rooted Android devices that works with DuraSpeed system configurations.

What it does

This app lets you manage which apps are included in your DuraSpeed whitelist by editing the /system/etc/duraspeed/configuration.xml file directly. The app will create it on first launch. If you already have a DuraSpeed configuration, it’ll load your existing settings without overwriting anything.

Features

  • View and manage apps: See all your installed apps in a clean, searchable list
  • Search functionality: Find apps quickly in the “All Apps” tab
  • Quick whitelist toggle: Add or remove apps with a single button press
  • Safe configuration handling: Preserves your existing DuraSpeed setup if it already exists
  • System controls: Built-in reboot and reset whitelist options with confirmation dialogs

Reboot after making changes to whitelist.

Download

DuraSpeed-Whitelist-Manager.apk (9.5 MB)

Screenshots

If something is not working correctly, let me know here:

7 Likes

WOWOW! Thanks so much!

5 Likes

Source code for the app:

https://github.com/alltechdev/F21Pro-duraspeed-whitelist

Dunno why it’s showing that description, just ignore.