Removing bloat apps will free enough RAM to fix the lag.
Field report · Wear OS teardown · 2026-11-02
Galaxy Watch 4 debloat: cleaner, not faster
Seventy-three packages removed, 300 MB of logs swept, animation scale halved. The watch is measurably cleaner and still swaps 40% of its ZRAM. This is the record of what was cut, what it bought, and the two readings that were misinterpreted along the way.
- Device
- Galaxy Watch 4, 44mm BT (SM-R870)
- SoC / RAM
- Exynos W920, 2 cores · 1376 MB
- Platform
- Android 16 / SDK 36
- Build
- R870XXS2JZG3
- Transport
- ADB over Wi-Fi
- Goal
- Fix lag and ~5 min cold boot
Debloat worked as cleanup (270 → 197 packages, −400 MB storage) but did not fix the lag: swap stayed at ~40%.
The CPU was 88% idle. High load average was processes waiting on ZRAM swap-in, not compute.
Swap is spread across ~18 core processes. Android 16 simply does not fit in 1.4 GB; there is no rogue app to remove.
One real defect found: a hidden watch face holding 252 MB at
oom_score_adj 0. Removed.Best fix for the original complaint: never let the watch power off, so the slow cold boot never happens.
Outcome
Everything was executed over ADB against the live device. The cleanup succeeded; the problem it was meant to solve did not move.
| Metric | Before | After | Read |
|---|---|---|---|
| Installed packages | 270 | 197 | −73 |
| Watch faces | 60 | 2 | active + emergency |
| Storage used | 2.9 GB | 2.5 GB | −400 MB |
/data/log | 265 MB | 2.2 MB | −263 MB |
| Animation scale | 1.0 | 0.5 | perceptible |
| Swap in use | 42% | 40% | within noise |
| MemAvailable | 381 MB | 306–366 MB | within noise |
Load average 6.9 on 2 cores means the CPU is saturated.
Lag is swap-in stall: the OS does not fit in 1.4 GB RAM.
Some hidden process holds memory it should not.
Diagnosis: load average lied, swap told the truth
A one-minute load average of 6.9 on a dual-core chip reads like a CPU pinned flat. It was taken as exactly that, and that reading was wrong. One command settled it.
Tasks: 379 total, 1 running, 378 sleeping, 0 stopped, 0 zombie
Mem: 1409864K total, 1344132K used, 65732K free, 1004K buffers
Swap: 986900K total, 417056K used, 569844K free, 345732K cached
200%cpu 9%user 0%nice 12%sys 176%idle 0%iow 3%irq 0%sirq
176% idle out of 200%. One task running out of 379. The CPU was asleep. Linux load average counts processes blocked in uninterruptible sleep alongside runnable ones, and those processes were blocked on ZRAM decompression, not on the scheduler. The lag was swap-in stall, and the 417 MB on the swap line is the whole story.
Swap was spread evenly across roughly eighteen processes at 28–50 MB each. Nine of the top ten are untouchable.
That distribution is the finding. There is no misbehaving app to evict — this is Android 16 not fitting inside 1.4 GB on 2021 silicon. The two removable entries total 75 MB and are both in daily use.
VmSwap per process, top 10 (MB)
- core (not removable)
- active watch face
- removable, but in daily use
Scale 0–60 MB.
The one real catch
A dormant watch face holding 252 MB at priority zero
Removing the third-party watch faces exposed something the first sweep had hidden.
healthmodular, a preinstalled face that was not selected and not visible,
was running a foreground service with thirty threads.
Proc # 6: fg b/ /SVC t: 0 8508:...watchface.healthmodular (exec-service)
RSS 251888 kB oom_score_adj 0 threads 30
compare — a genuinely idle face:
Proc #12: cch+ 5 b/ /CEM t: 0 9152:...watchface.mystyle (cch-empty)
RSS 52436 kB oom_score_adj 905 threads 25
healthmodular · not active
Bugmystyle · idle
Normal
oom_score_adj = 0 places a process on par with the active foreground app:
under memory pressure the kernel will not reclaim it. Its neighbour at 905 is discarded
the instant anything needs the pages. This was the only genuine defect found all session,
and it is gone. Its effect shows up under pressure rather than at idle, which is exactly
where an idle snapshot cannot see it.
How the investigation actually ran
Including the detours. Two measurements were read wrong before the right instrument was found, and both misreads pointed at work that turned out to be worthless.
- Connect over Wi-Fi
Wireless debugging on Wear OS uses Android 11-style pairing: a random port and a six-digit code, distinct from the connect port. Pairing persists across reboots; the port does not, and wireless debugging switches off on every restart.
- First reading: MemFree at 76 MB Wrong metric
Interpreted as acute RAM starvation. The top-RSS table was used to rank removal candidates, which put Play Store at 152 MB in first place.
- Fourteen packages removed, then a reboot No effect
Play Store, Bixby, Smart Switch, diagnostic telemetry, Knox EMM, Global Goals, two leftover test faces. MemAvailable moved from 381 MB to 383 MB. Play Store and the FOTA agent were restored.
- Watch faces: 58 removed, one defect exposed Real finding
Each candidate was checked for a
WallpaperServicebefore deletion, which correctly sparedtickingsound(not a face) andemergency(the low-power emergency display). Removing the rest surfacedhealthmodular. - Second reading: load average 6.9 / 8.2 / 10.1 Wrong conclusion
Interpreted as a saturated dual-core CPU. It was not.
topshowed 88% idle in the same minute; the queue was swap-wait, not compute. - Sampling MemAvailable three times, 20 s apart Instrument corrected
351 MB, then 335 MB, then 366 MB: a ±30 MB swing on an untouched device. Every single-snapshot comparison made earlier fell inside that band and proved nothing.
- Cache and log sweep Storage only
/data/logheld 265 MB. easyMover held 222 MB of orphaned data (every removal used-kto stay reversible, which keeps app data behind). Reclaimed roughly 300 MB. Swap did not move. - Stop
Nothing further is worth removing. The remaining consumers are the operating system.
Ledger: what went and what stayed
Every removal used pm uninstall -k --user 0, which detaches the package from the user profile while leaving the APK on the system partition. Nothing here needs a factory reset to undo (restore.sh).
Removed
73 packages · reversiblecom.google.android.apps.maps | |
com.google.android.apps.youtube.music | |
com.microsoft.office.outlook | |
com.samsung.android.bixby.agent | Bixby |
com.samsung.sree | Global Goals |
com.samsung.sree.classic | Global Goals |
com.samsung.sree.countdown | Global Goals |
com.samsung.sree.digital | Global Goals |
com.samsung.sree.spin | Global Goals |
com.sds.emm.cloud.knox.samsung | enterprise MDM |
com.sec.android.diagmonagent | telemetry |
com.sec.android.easyMover | Smart Switch |
com.whatsapp |
60 watch face packages (58 in the face sweep + 2 test faces)
…watchface.activitynumber…watchface.analogmodular…watchface.analoguefont…watchface.analogutility…watchface.animal…watchface.aremoji…watchface.basicclock…watchface.basicdashboard…watchface.bespoke…watchface.bitmoji…watchface.boldindex…watchface.breathe…watchface.casualminimalist…watchface.classic…watchface.classicadventurer…watchface.digitalfont…watchface.digitalmodular…watchface.digitalneon…watchface.dualwatch…watchface.endangeredanimal…watchface.face…watchface.fitfuture…watchface.fitnesscentric…watchface.flower…watchface.fresh…watchface.frontier…watchface.gradientfont…watchface.healthdashboard…watchface.healthmodular…watchface.infomodular…watchface.intrepid…watchface.large…watchface.livewallpaper…watchface.modernminimalist…watchface.mypebble…watchface.myphoto…watchface.mystyle…watchface.photosticker…watchface.premiumanalog…watchface.quadhive…watchface.rosegold…watchface.simpleanalogue…watchface.simplebasic…watchface.simpleclassic…watchface.simplecomplication…watchface.simpledigital…watchface.sleepcoaching…watchface.solariboard…watchface.spatialnumber…watchface.spherenumber…watchface.stretchindex…watchface.superfiction…watchface.together…watchface.tomcat…watchface.typography…watchface.ultrainfoboard…watchface.weathercom.watchfacestudio.Test_23924081946917534797456318269746com.watchfacestudio.Test_23924081946917536609753408129222de.mindfabrik.watchface.android.dos
Kept deliberately
each for a stated reasoncom.android.vending | sole installer on device (Play Store) |
com.wssyncmldm | firmware OTA agent |
…wear.shealth | sensor stack + history |
…wearable.assistant | in daily use |
…watchface.emergency | emergency display |
…watchface.tickingsound | not a face |
complicationhelper | infrastructure |
companionhelper | infrastructure |
wear.watchface.runtime | infrastructure |
Recommendation
Two options remain, and the first one is the owner's own.
Never let it power off
Wear OS cold boot is inherently slow on this hardware: re-sync to the phone, re-index, restart every service. No amount of debloating shortens it. Enable Battery Protection at an 85% ceiling, charge regularly, never reach 0%. The watch never boots, so the five-minute wait never happens.
Factory reset
Not to remove apps, but to drop four or five years of accumulated app data and
profiles that pm clear cannot reach on an uninstalled package. The only
remaining lever with real odds, at the cost of a full re-pair and re-setup.
Not recommended
Clearing Galaxy Store (114 MB), GMS (110 MB) or TTS (53 MB) data. All storage-only wins on a device with 6.1 GB free; clearing GMS risks breaking account sync. Removing Samsung Health would take the sensor history with it.
Reconnecting
Wireless debugging turns itself off after every reboot. Pairing from this session is already stored, so step 2 is usually unnecessary.
- Enable wireless debugging on the watch
Settings › Developer options › Wireless debugging › on
- Pair (once)
adb pair <ip>:<pairing-port> <6-digit-code> - Connect
adb connect <ip>:<connect-port> # or let mDNS find it - Check the watch
./watchstat.sh -w # RAM / swap / load / disk / battery, refresh 5s
Files
Raw artifacts in this folder. Captured during the session; don't edit.
README.md
Session summary in plain text
removed.txt
The 73 removed packages
packages-before.txt
All 270 packages before any change
packages-after.txt
197 packages (before minus removed)
watchstat.sh
RAM / swap / load / disk / battery over ADB. -w for live refresh
restore.sh
Restore all 73 packages, or named ones