MiBudsM8 Crash Fix: ArrayIndexOutOfBoundsException on Custom ROMs
Description
The MiBudsM8 app (bz.zaa.mibudsm8) crashes with an ArrayIndexOutOfBoundsException when opening the touch gesture settings screen on AOSP-based custom ROMs (LineageOS, Matrixx, etc.). The crash occurs because the app depends on a MIUI-specific system service (com.android.settings.bluetooth.MiHeadsetService) that does not exist on non-MIUI ROMs.
Problem
Root Cause
MiuiHeadsetActivity.x() tries to reflectively load com.android.settings.bluetooth.MiHeadsetService
- On AOSP ROMs this throws
ClassNotFoundException, which is silently caught
- This causes the cached Bluetooth device lookup to return
null
- The null propagates through
kn0.p() which returns an empty string ""
kn0.r("") converts the empty string to a zero-length byte array (byte[0])
kn0.t() attempts to access indices 0–8 of the empty byte array → ArrayIndexOutOfBoundsException
Crash Stack Trace
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at kn0.t(:29)
at kn0.onCreateView(:67)
Caused by: java.lang.ClassNotFoundException: com.android.settings.bluetooth.MiHeadsetService
at bz.zaa.mibudsm8.ui.activities.MiuiHeadsetActivity.x(:3)
Solution
Add a bounds check in kn0.t() before accessing array elements. If the byte array is shorter than 9 bytes, initialize all fields with defaults and return early instead of crashing.
Original Smali (kn0.smali method t())
invoke-static {v0}, Lkn0;->r(Ljava/lang/String;)[B
move-result-object v0
const/4 v1, 0x0
aget-byte v2, v0, v1 ; CRASH: v0 is empty!
iput v2, p0, Lkn0;->y:I
Patched Smali
invoke-static {v0}, Lkn0;->r(Ljava/lang/String;)[B
move-result-object v0
array-length v4, v0
const/16 v2, 0x9
if-ge v4, v2, :array_ok ; only access array if length >= 9
; Fallback: zero out all fields and return
const/4 v1, 0x0
iput v1, p0, Lkn0;->y:I
iput v1, p0, Lkn0;->z:I
iput v1, p0, Lkn0;->A:I
iput v1, p0, Lkn0;->B:I
iput v1, p0, Lkn0;->D:I
iput v1, p0, Lkn0;->F:I
const/4 v1, 0x0
iput-boolean v1, p0, Lkn0;->C:Z
iput-boolean v1, p0, Lkn0;->E:Z
return-void
:array_ok ; original array access code (unchanged)
const/4 v1, 0x0
aget-byte v2, v0, v1
iput v2, p0, Lkn0;->y:I
; ... rest of original code
Equivalent Java Logic
byte[] config = r(p()); // r() converts hex string to byte array
if (config.length >= 9) {
// Original code: parse gesture config from byte array
this.y = config[0];
this.z = config[2];
this.A = config[1];
this.B = config[3];
this.D = config[4];
this.F = config[8];
} else {
// Fallback: use default values
this.y = 0; this.z = 0; this.A = 0;
this.B = 0; this.D = 0; this.F = 0;
this.C = false; this.E = false;
}
Affected File
smali/kn0.smali — method t() (r8 mapping: kn0.t)
- Called by
kn0.onCreateView which is the gesture settings fragment
Compatibility
- Broken on: AOSP-based ROMs (LineageOS, Matrixx, crDroid, etc.)
- Works on: MIUI/HyperOS (has
MiHeadsetService)
- Fix tested on: Redmi 8A (olivelite) running LineageOS
Test Environment
Device: Xiaomi Redmi 8A
| Property |
Value |
| Model |
Redmi 8A (olivelite) |
| Manufacturer |
Xiaomi |
| SoC |
Qualcomm Snapdragon 439 (SDM439) |
| CPU |
8× Cortex-A53 @ 1.95 GHz (4× A53 + 4× A53) |
| Architecture |
aarch64, ARMv8 |
| GPU |
Adreno 505 |
| RAM |
1.8 GB (1868944 kB) |
| Storage |
32 GB eMMC (22 GB userdata) |
| Display |
720×1520, 320 dpi |
| Battery |
5000 mAh |
| Android Version |
11 (API 30) |
| ROM |
LineageOS 18.1 (UNOFFICIAL) |
| ROM Version |
18.1-20260209-UNOFFICIAL-Mi439_4_19 |
| Build Fingerprint |
Xiaomi/olive/olive:10/QKQ1.191014.001/V12.5.1.0.QCNMIXM:user/release-keys |
| Kernel |
4.19.325-Tiopaz-4.19 #1 SMP PREEMPT aarch64 |
| App Version |
MiBudsM8 1.19.0-beta0 (versionCode=129000) |
| App Target SDK |
35 (Android 15) |
| App Min SDK |
21 (Android 5.0) |
Headset: Redmi Buds 6 Active
| Property |
Value |
| Name |
Redmi Buds 6 Active |
| MAC Address |
24:B2:31:06:34:21 |
| Vendor ID |
10007 (0x2717) |
| Product ID |
20617 (0x5089) |
| Firmware Version |
3.0.3.4 (versionCode=12340) |
| UBoot Version |
1.0.3.2 (versionCode=4146) |
| Codec |
SBC (supports AAC, LDAC) |
| Sample Rate |
44100 Hz |
| Bits Per Sample |
16 |
| Channel Mode |
Stereo |
| Battery (L/R/Case) |
30% / 30% / Charging |
| Color Type |
3 |
| Support Power Mode |
0 |
| Support Function Key |
0 |
| Support Hot Word |
0 |
MiBudsM8 Crash Fix:
ArrayIndexOutOfBoundsExceptionon Custom ROMsDescription
The MiBudsM8 app (
bz.zaa.mibudsm8) crashes with anArrayIndexOutOfBoundsExceptionwhen opening the touch gesture settings screen on AOSP-based custom ROMs (LineageOS, Matrixx, etc.). The crash occurs because the app depends on a MIUI-specific system service (com.android.settings.bluetooth.MiHeadsetService) that does not exist on non-MIUI ROMs.Problem
Root Cause
MiuiHeadsetActivity.x()tries to reflectively loadcom.android.settings.bluetooth.MiHeadsetServiceClassNotFoundException, which is silently caughtnullkn0.p()which returns an empty string""kn0.r("")converts the empty string to a zero-length byte array (byte[0])kn0.t()attempts to access indices 0–8 of the empty byte array →ArrayIndexOutOfBoundsExceptionCrash Stack Trace
Solution
Add a bounds check in
kn0.t()before accessing array elements. If the byte array is shorter than 9 bytes, initialize all fields with defaults and return early instead of crashing.Original Smali (
kn0.smalimethodt())invoke-static {v0}, Lkn0;->r(Ljava/lang/String;)[B move-result-object v0 const/4 v1, 0x0 aget-byte v2, v0, v1 ; CRASH: v0 is empty! iput v2, p0, Lkn0;->y:IPatched Smali
invoke-static {v0}, Lkn0;->r(Ljava/lang/String;)[B move-result-object v0 array-length v4, v0 const/16 v2, 0x9 if-ge v4, v2, :array_ok ; only access array if length >= 9 ; Fallback: zero out all fields and return const/4 v1, 0x0 iput v1, p0, Lkn0;->y:I iput v1, p0, Lkn0;->z:I iput v1, p0, Lkn0;->A:I iput v1, p0, Lkn0;->B:I iput v1, p0, Lkn0;->D:I iput v1, p0, Lkn0;->F:I const/4 v1, 0x0 iput-boolean v1, p0, Lkn0;->C:Z iput-boolean v1, p0, Lkn0;->E:Z return-void :array_ok ; original array access code (unchanged) const/4 v1, 0x0 aget-byte v2, v0, v1 iput v2, p0, Lkn0;->y:I ; ... rest of original codeEquivalent Java Logic
Affected File
smali/kn0.smali— methodt()(r8 mapping:kn0.t)kn0.onCreateViewwhich is the gesture settings fragmentCompatibility
MiHeadsetService)Test Environment
Device: Xiaomi Redmi 8A
Xiaomi/olive/olive:10/QKQ1.191014.001/V12.5.1.0.QCNMIXM:user/release-keys4.19.325-Tiopaz-4.19#1 SMP PREEMPT aarch64Headset: Redmi Buds 6 Active