The release of MIUI 12 brought a long-standing battle between App developers and ROM developers into the public eye, revealing the intricate details of this technical tug-of-war. As the saying goes, “While the demon rises a foot, the path rises ten feet.” ROM developers, with their higher system-level permissions, generally hold the upper hand. App developers, however, are not easily deterred, employing various “black technologies” for background persistence and cross-app wakeups. Even Google has stepped in to mediate, establishing rules to regulate behavior for both parties. This competition is arguably healthy; a total victory by either side would inevitably lead to stagnation or the loss of useful functionality.
However, the victims of this struggle are undoubtedly the consumers. If App developers succeed, phones become cluttered with persistent background processes that hog CPU and memory. Conversely, if ROM developers are too aggressive, the app experience suffers—a pain well-known to many Android developers.
As discussed later in this article, most smartphone manufacturers have developed their own strategies to handle auto-starts and associated starts. Beyond the technical struggle, there’s the issue of privacy. Baidu’s Robin Li once remarked that “Chinese people are more open about privacy and relatively less sensitive. If they can trade privacy for convenience, safety, or efficiency, they are willing to do so in many cases.” Consider the convenience of copying a phrase in WeChat and having Taobao automatically open to the corresponding item. It’s helpful, isn’t it? But do we really want every app peering into our clipboards?
Privacy should not be dismissed lightly. Technology is a double-edged sword. If privacy falls into the wrong hands, the consequences can be severe. This is exactly why the EU implemented the General Data Protection Regulation (GDPR). For example, many domestic manufacturers now differentiate their products for the EU market, disabling various data collection features to avoid massive fines. In other markets, data collection often remains unchecked.
This article does not delve into the ethics of privacy—I unconditionally support privacy protection. Instead, I will analyze the technical aspects of “Auto-start” and “Chain Wakeup” as highlighted by MIUI 12.
Version note (reviewed 2026-10-14): The personal discussion and AOSP Android 10 cases retain their 2020 context. App/SDK versions were not fully recorded; these observations do not establish current behavior. This review separates receiver declarations, actual process starts, and evidence of the caller. Old OEM settings and SDK snippets are historical, with relevant Android 7–15 restrictions added below.
Technical Terminology Explained
Distinguish processes, components, and launch causes before treating a component record as another app startup.
Process Startup
Android’s four app component types are Activity, Service, BroadcastReceiver, and ContentProvider. A process hosts components; it is not an additional component category. Apps normally use a default process but can assign components to other processes created by the system, rather than child processes forked by the app’s main process. See Application fundamentals.
For an allowed request, the system reuses the required process or creates it when absent. Tapping a launcher icon can reuse an existing process and Activity. A context-registered receiver requires a running process; it is not equivalent to a manifest receiver that can trigger a cold start. A file observer cannot execute after its hosting process is gone.
This article focuses on Receiver, Service, and Provider paths without a new visible screen. Background Activity launches also face platform restrictions since Android 10. Starting a process or component does not mean an app UI has appeared.
Auto-start (Self-starting)
Here, “auto-start” means a process launch triggered by a system event or scheduled task without the user opening the app at that moment. It is an analysis term, not one Android API; the system still determines eligibility and timing.
Associated Start (Link-starting / Chain Wakeup)
Here, an associated start means one app’s cross-app component request causes another process to launch. A shared SDK can participate, but sharing an SDK alone is insufficient: visibility, exported status, permissions, target state, and background restrictions still apply.
Startup Blocking
ROM policy can act during resolution, requests, or process creation; AOSP already applies permission, background-execution, and state checks. A request may be rejected, deferred, or fail with an exception, rather than simply returning silently.
Imagine tapping Alipay to pay inside another app, only for the system to block the payment component. User-initiated payment and sharing flows need different treatment from background maintenance. Incorrect blocking breaks legitimate behavior; allowing one request does not grant permanent process residency.
Analysis Methods
Monkey
Monkey generates activity launches and input pressure, but is not required to establish a launch cause. For a single chain wakeup, record the build, app versions/targetSdk, initial process state, and one controlled action. For my original experiment, I installed plenty of apps, started the Monkey command below, and went to bed while it kept generating activity switches. That is the background to this long-running stress test, not a default reproduction command:
1 | adb shell monkey --kill-process-after-error --ignore-security-exceptions --ignore-crashes --pct-appswitch 90 --pct-touch 10 --throttle 10000 --ignore-timeouts --ignore-native-crashes 100000000 |
--pct-appswitch 90 controls the share of Activity-launch events, not a guarantee of switching to different apps 90% of the time. --throttle 10000 sets a 10-second delay, while 100000000 is an event count. A rough count-times-delay estimate is 31.7 years; event combinations and termination conditions affect actual duration. It is not an overnight completion setting, and ignored failures remain failures.
Using the official options, start with bounded sampling on a dedicated test setup, replacing the package with the app under test:
1 | adb shell monkey -p com.example.app -s 20200507 --pct-appswitch 90 --pct-touch 10 --throttle 500 -v 200 |
-p constrains Activities visited by Monkey, not system broadcasts or other processes requested by the app. A seed does not freeze networking, scheduling, or background jobs. These commands were not executed during this review.
EventLog
Process events are useful clues, but buffers can wrap and captures can be incomplete. Preserve raw context before filtering:
1 | adb logcat -b events -v threadtime > events.log |
For a quick live view:
1 | adb logcat -b events -v threadtime | grep -E 'am_proc_died|am_proc_start|am_proc_bound' |
Android 10 EventLogTags defines the fields. am_proc_bound records binding the app process to system work; it does not establish a successful service bindService call or visible Activity. Correlate timestamps, user, and UID because PIDs are reused.
Dumpsys
The original used dumpsys activity. Narrower snapshots help inspect broadcasts and the target service:
1 | adb shell dumpsys activity |
Connections identifies binding clients at capture time, not a complete call history. Align snapshots with launch events, caller logs, or system tracing from the same interval. Record the build, app version, targetSdk, user ID, and capture time.
Technical Analysis of Auto-starts
The boot, network, and media cases below are historical. The existence of a broadcast does not mean every targetSdk can receive it through a manifest and cold-start a process; eligibility and delivery still require checking.
Boot Completed
1 | android.intent.action.BOOT_COMPLETED |
BOOT_COMPLETED requires RECEIVE_BOOT_COMPLETED and is not delivered in every state, including an ordinary never-launched installation or a force-stopped package. It differs from LOCKED_BOOT_COMPLETED during Direct Boot, which requires appropriate directBootAware and device-encrypted storage handling.
Boot broadcasts are exceptions to Android 8.0’s implicit-broadcast restrictions, but receiving one does not allow unlimited background execution. Finish onReceive promptly; deferrable backup/sync work can use WorkManager, which follows system scheduling and does not guarantee immediate execution or permanent residency.
Case Study: Tencent News
The original record describes a boot broadcast. The cropped image identifies com.tencent.news.system.BootBroadcastReceiver with process com.tencent.news:PushService, not the default process named in the old explanation.

Deliver +7s128ms does not directly mean seven seconds executing onReceive. Android 10 BroadcastRecord prints duration[i], assigned by BroadcastQueue.finishReceiverLocked from finishTime minus receiverTime. For a manifest receiver this interval can include process startup, dispatch, and waiting. It is approximately 7.128 seconds of system-tracked handling, not CPU time. The crop omits the action and matching am_proc_start, so it cannot independently establish a new process creation.
Network Changes
1 | android.net.conn.CONNECTIVITY_CHANGE |
Suppose you’re watching a live stream and Wi-Fi drops, switching you to mobile data. The app can ask whether you want to keep watching; streaming uses a lot of data. Network changes can inform app behavior. However, CONNECTIVITY_ACTION was deprecated in API 28. On Android 7.0 (API 24) and later, apps targeting 24+ cannot receive it through a manifest receiver; context registration works while that context remains valid, not as a replacement for cold-starting a dead process.
Use registerDefaultNetworkCallback/registerNetworkCallback for network observation, or WorkManager network constraints for deferrable sync. A connected network does not guarantee that the destination server is reachable.
Examples
I listed these receivers in my notes at the time:
- DingTalk (
com.alibaba.android.rimet):com.xiaomi.push.service.receivers.NetworkStatusReceiver - Learning Strong Nation (
cn.xuexi.android):com.xiaomi.push.service.receivers.NetworkStatusReceiver - Weibo (
com.sina.weibo):com.xiaomi.push.service.receivers.NetworkStatusReceiver - DiDi (
com.sdu.didi.psnger):com.didi.sdk.push.PushNetReceiver - Inke (
com.meelive.ingkee):com.network_optimization.NetWorkStateReceiver

The crop actually shows Learning Strong Nation and DingTalk as Pending, with maxManifestReceiverApiLevel=23. Android 10’s dispatch code checks targetSdk against that limit and can skip candidates. This is not evidence that every listed process started. The original “over 200” count cannot be verified from the retained crop.
1 | android.net.wifi.STATE_CHANGE |

This is another Pending list, including Tencent Mobile Manager and UC receivers. The Wi-Fi action differs from CONNECTIVITY_CHANGE; ordinary apps targeting 26+ also face Android 8.0’s manifest implicit-broadcast restrictions. These images are not current universal auto-start recipes.
Media Library Scanning
1 | android.intent.action.MEDIA_SCANNER_STARTED |
The first two describe the beginning/end of a directory scan; the third concerns a request to eject external storage. They are not a broadcast to every app for every new file. The implicit-broadcast exemption list includes MEDIA_EJECT and other storage-state events, not a blanket exemption for scanner broadcasts. Media access still requires applicable permissions and storage rules.
Case Study: JD Finance
The original presented this as an auto-start case. The image shows com.jd.jrapp.library.longconnection.receiver.BootReceiver as Pending #0 for MEDIA_SCANNER_STARTED, with data file:///storage/emulated/0:

It establishes inclusion in the broadcast record, not successful delivery or process creation. Those conclusions require subsequent delivery results and a matching am_proc_start.
Third-Party SDKs (e.g., GeTui)
Push SDKs may declare background components, but a process suffix cannot identify the SDK. Multiple libraries can use :pushservice. Inspect actual APK dependencies, the merged manifest, and runtime evidence.
The following 2020 snippet has no recorded SDK version and is retained to identify historical components, not as a current integration template:
1 | <service |
The receiver has an intent-filter without an explicit exported value. Components with intent filters targeting API 31+ must declare exported explicitly; choose the value according to purpose and permissions, not by making everything public. GeTui’s current integration guide says it applies to SDK 3.1.2.0 and later and uses Maven/AAR configuration with matching dependencies. Follow the version in use instead of adding this old XML on top.

Although the process is com.ss.android.ugc.aweme:pushservice, the receiver is com.taobao.accs.EventReceiver, still Pending. The image does not establish a GeTui-triggered Douyin startup, or whether other SDKs are present in that APK.
Technical Analysis of Associated Starts (Chain Wakeups)
Shared SDKs may contact accessible services or providers, subject to platform checks. The old experiment does not support a general claim that most chain wakeups come from JPush. Here we examine only the retained JPush component records.
1 | [0,19428,10195,com.qq.reader,service,{com.qq.reader/cn.jpush.android.service.DaemonService}] |
The Android 10 schema gives six fields: user 0, new process PID 19428, UID 10195, process com.qq.reader, type service, and component cn.jpush.android.service.DaemonService. UID is not the caller PID; this entry does not identify the requester.
Case Study: Qidian Launching QQ Reader via JPush
In that experiment, I ran adb shell am force-stop com.qq.reader, then watched EventLog for a start. Force-stop changes package stopped state; it is not equivalent to LMK reclaiming a process, normal process exit, or swiping away a recent task. The image alone cannot reconstruct every action between the stop and the next request.

The screenshot records 05-06 08:48:35.337, PID 4302, followed by am_proc_bound for the same PID. The textual example above has PID 19428 and must not be treated as this same launch record.

EventLog had not told me who made the request, so I next looked at QQ Reader’s ServiceRecord. It hosts PID 4302 and lists client 2808:com.qidian.QDReader:pushcore/u0a174. This establishes a binding relationship at capture time and a lead for caller analysis, not proof that this connection first created the process. started=false reflects startRequested at that moment; it does not mean the service never ran.
ActiveServices’ compact dump prints the binding Intent before the client, so flg=0x20 is Intent.FLAG_INCLUDE_STOPPED_PACKAGES, not bindService flags. It cannot determine whether BIND_AUTO_CREATE was used. Android 10’s service launch path also clears package stopped state; that explains an old platform mechanism, not the complete sequence behind the screenshot.
To establish causality, align the service request’s caller UID/PID, component, bind/start flags, and process creation, then compare runs changing only the triggering action. The original experiment had no MIUI 12 device screenshot, so the claim that its UI displayed “Qidian launched QQ Reader at 8:48” was an illustration, not a verified UI result.
Newer boundary: Android 15’s stopped-state changes require direct or indirect user action to leave stopped state and cancel PendingIntents on force-stop. The Android 10 observation is not a general method for bypassing current force-stop behavior.
JPush Wakeup Configuration
This historical callback document lists startService, bindService, and ContentProvider types. SDK callback reporting does not replace system evidence about the caller and timing.

JPush Associated-start Documentation
The old documents mention service wakeups in JPush 1.8.0 and shared channels in 3.1.6. Their component switches and VIP terms should not be presented as today’s product rules.


The current Android API documentation separately lists JCollectionAuth.enableAutoWakeup for auto-start and JPushInterface.setLinkMergeEnable for link merging; false disables the corresponding feature. These sections do not identify their earliest supported versions, so check the actual JPush/JCore dependencies. Do not assume an old APK supports them or that one switch disables every background entry point. Vendor power/delivery claims are not new measurements from this review.
OEM Responses
This was my experience with the test phone I had in 2020:
Process management is the most contested area in Android. MIUI chose to show this battle to users, but other manufacturers do the same quietly behind the scenes. Without these controls, phones would be unusable. On my test Pixel, processes are constantly killed by the Low Memory Killer (LMK) due to low RAM, only to be immediately restarted, draining the battery and making the phone so painfully slow I could barely recognize it.
The old settings list is outdated and retained only as historical context. Menus and behavior vary by vendor, OS version, region, and model; no current per-device testing is available here. Notification controls, background restrictions, and force-stop are distinct. Allowlisting does not guarantee survival.
JPush White-list Configurations
This original vendor-settings image includes legacy entries such as MIUI 7’s hidden mode; it is not a current universal menu guide:

GeTui White-list Configurations
EMUI OS (Huawei)
The old document lists auto-start, background protection, and notification controls. These govern different behavior; “manual launch is the only way to recover” is not a cross-version guarantee.
Flyme OS (Meizu)
The old list includes auto-start and notification switches. Blocking notification display does not stop a process; background scheduling follows the actual system policy.
Funtouch OS (VIVO)
The old path uses iManager. Cleanup, force-stop, and system reclaim are different operations; allowlist membership alone cannot predict a later start.
Color OS (OPPO)
The old document mentions Pure Background and locking a process. These are not universal current menu paths, and a recent-task lock is not Android’s promise of permanent residency.
MIUI OS (Xiaomi)
The old list includes auto-start management, battery policy, and MIUI 7 hidden mode. Retain these names for interpreting old records. Background network availability and message timing require testing the actual version; there is no universal “disconnected after a few minutes” rule.
Across ROMs, also check platform limits: background services and implicit broadcasts for targetSdk 26+; background foreground-service launch limits and exceptions for targetSdk 31+; and deferred boot broadcasts on Android 13+ for restricted apps targeting 33+. Android 14/15 impose additional limits on certain FGS types launched from boot receivers. Notification permission is separate from permission to execute in the background.
About Me && Blog
Below are my personal details and links. I look forward to connecting and sharing knowledge with fellow developers!
- About Me: Includes my WeChat and WeChat group links.
- Blog Navigation: A guide to the content on this blog.
- Curated Android Performance Articles: A collection of must-read performance optimization articles. Self-nominations/recommendations are welcome!
- Android Performance Knowledge Planet: The paid community stopped operating in 2026 and no longer accepts new members; this link preserves its history.
“If you want to go fast, go alone. If you want to go far, go together.”
