Jank, Responsiveness, and ANR often appear together and can share contributing causes, but they are not severity levels of one mechanism. Uneven visual progress, delayed feedback, and an ANR triggered by a particular timeout need separate evidence. Treat a user’s “the app is slow/stuttering” as an experience report first, then establish which action and outcome are delayed.
Uneven animation or scrolling is usually called Jank. Long startup, screen-wake, or transition delays are slow response / high latency; ANR means Application Not Responding. These categories can overlap. High latency can coexist with jank, while ANRs must be diagnosed by their specific trigger.
Furthermore, within Apps or manufacturers, Jank, Responsiveness, and ANR have individual metrics like Frame Drop Rate, Startup Speed, and ANR Rate. Mastering the analysis and optimization of these issues is crucial for developers.
This is the first article in the Responsiveness series, focusing on theoretical knowledge, including an overview of performance engineering, key responsiveness concepts, and analysis methodologies.
Version note (reviewed 2026-10-14): Originally published in 2021, this article retains its methodology, book passage, and figure. It corrects the assumptions that thread states identify app/system responsibility and that Message completion means response completion. Startup initialization references AOSP android-11.0.0_r1, with added TTID/TTFD, Android 12 (API 31) SplashScreen, and current-tool boundaries.
Table of Contents
- Performance Engineering
- Responsiveness Overview
- Methodology for Analyzing Responsiveness Issues
- Series Articles
- References
- About Me && Blog
For articles on Jank, refer to Systrace Smoothness in Action 1: Understanding Jank Principles. ANR articles will follow. This article focuses on the basic principles of responsiveness.
If you are not familiar with the basic use of Systrace (Perfetto), please catch up on the Systrace Basics Series first. This article assumes you are already familiar with using Systrace (Perfetto).
Performance Engineering
Before introducing responsiveness principles, here is a passage from the book “Systems Performance” regarding performance. It fits the questions we’re discussing here. If you work on performance, I recommend keeping it close at hand and returning to its methods:
Performance is Challenging
Systems performance engineering is a challenging field for many reasons, including the facts that system performance is subjective, complex, and often characterized by multiple concurrent issues.
Performance is Subjective
- Technical disciplines are often objective; many in the industry view problems as black or white. In software troubleshooting, deciding whether a bug exists or is fixed is usually clear-cut. Bugs are accompanied by error messages that are often easy to interpret, leading you to understand why the error occurred.
- In contrast, performance is often subjective. When starting on a performance issue, judging whether a problem even exists can be ambiguous, and the same applies when it is fixed. What one user considers “poor” performance, another might consider “good.”
Systems are Complex
- Besides subjectivity, performance engineering is challenging because systems are complex and often lack a clear starting point for analysis. We often begin with guesses—blaming the network, for example—and performance analysis must determine if that is a correct direction.
- Performance issues can arise from complex interconnections between subsystems, even when those subsystems perform well in isolation. They can also result from cascading failures, where one failing component causes performance issues in others. To understand these, you must untangle component relationships and how they collaborate.
- Bottlenecks are often complex and interconnected in unexpected ways. Fixing one issue might simply push the bottleneck elsewhere, resulting in no overall performance gain.
- Additionally, the complexity of production workloads can cause issues that are difficult to reproduce in a lab or occur only intermittently.
- Solving complex performance problems often requires a holistic approach. The entire system—including internal and external interactions—may need investigation. This work demands a broad skill set, rarely found in one person, making performance engineering a dynamic and intellectually challenging endeavor.
Multiple Issues May Coexist
- Finding a single performance issue is often not the end; complex software usually has multiple problems.
- Another difficulty: the real task isn’t just finding problems, but identifying which ones are the most significant.
- To do this, performance analysis must quantify the importance of issues. Some problems may not apply to your workload or only to a small degree. Ideally, you should not only quantify the problem but also estimate the speedup expected after fixing it. This information is especially useful when management reviews engineering or operations resource allocation.
- One metric is particularly well-suited for quantifying performance: latency.
– Excerpts from “Systems Performance: Enterprise and the Cloud” (paraphrased)
The retained passage motivates attention to perception and system complexity; it does not mean latency cannot be measured objectively. Bugs can also occur without error logs. Defined boundaries, workload, and measurement procedures make performance comparisons repeatable. See the author’s book page.
Systrace Series Articles:
- Introduction to Systrace
- Systrace Basics - Prerequisites for Systrace
- Systrace Basics - Why 60 fps?
- Android Systrace Basics - SystemServer Explained
- Systrace Basics - SurfaceFlinger Explained
- Systrace Basics - Input Explained
- Systrace Basics - Vsync Explained
- Systrace Basics - Vsync-App: Detailed Explanation of Choreographer-Based Rendering Mechanism
- Systrace Basics - MainThread and RenderThread Explained
- Systrace Basics - Binder and Lock Contention Explained
- Systrace Basics - Triple Buffer Explained
- Systrace Basics - CPU Info Explained
- Systrace Smoothness in Action 1: Understanding Jank Principles
- Systrace Smoothness in Action 2: Case Analysis - MIUI Launcher Scroll Jank Analysis
- Systrace Smoothness in Action 3: FAQs During Jank Analysis
- Systrace Responsiveness in Action 1: Understanding Responsiveness Principles
- Systrace Responsiveness in Action 2: Responsiveness Analysis - Using App Startup as an Example
- Systrace Responsiveness in Action 3: Extended Knowledge on Responsiveness
Responsiveness Overview
Responsiveness is a critical metric for App performance. Poor responsiveness typically manifests as delayed click effects, operation wait times, or prolonged white screens. Primary scenarios include:
- App startup scenarios: Cold start, hot start, warm start, etc.
- Interface transition scenarios: Page jumps within an App, or between different Apps.
- Non-transition click scenarios: Toggles, pop-ups, long presses, control selections, single/double clicks, etc.
- Screen wake/sleep, power on/off, unlocking, facial recognition, camera, video loading, etc.
Define response time as the interval from an agreed trigger to an agreed outcome. Triggers can be touch, notifications/Intents, system actions, or app events. Touch input enters through InputChannel/native Looper processing, not a direct Java Message for every hardware event. Long presses are typically recognized by gesture logic; fingerprint recognition uses separate hardware/service callbacks.
The endpoint can be initial button feedback, the first page frame, significant content becoming usable, a captured photo, or actual screen illumination. Name each metric explicitly. Worker, network, GPU, composition, and display waits may remain after a main-thread Message finishes. The figure shows app events interleaved with UI drawing, not a complete response path.

Expectations vary, but latency within agreed boundaries is objectively measurable. Smoothness also needs a defined target cadence and presentation criterion. “Subjective response versus purely objective jank” is too simple. Roles can choose different scopes, provided they name them:
| Scope | Possible boundaries | What it can miss |
|---|---|---|
| System/end-to-end | Defined input event or launch request → result/presentation | Physical contact, interrupt, and InputReader timestamps differ; logs may not cover optical display |
| App-stage | attachBaseContext / Application.onCreate → app readiness |
Earlier scheduling/process creation; starting at onCreate can also miss Provider initialization |
| Experience test | Automated/physical trigger → agreed visual or usable outcome | Icon highlighting is already feedback, so starting there excludes prior delay; camera/recognition adds sampling error |
These are choices, not mandatory role-specific procedures. Cameras, automation, app markers, and system evidence can complement one another; no single equipment setup is a universal industry standard.
Startup metrics: Android distinguishes TTID and TTFD. TTID covers framework-defined startup through first display, observable through Displayed; TTFD adds app-reported readiness of significant content. Neither automatically represents the entire physical-touch-to-result path.
Activity.reportFullyDrawn(), available since API 19, should reflect agreed readiness of significant data and UI. Early/late calls change its meaning; no report means missing data. Android 12 (API 31) SplashScreen adds a system launch surface and exit transition. Distinguish that surface, the app’s first frame, significant content, and interactivity. Faster placeholder feedback does not mean the underlying work finished sooner.
Methodology for Analyzing Responsiveness Issues
Define the Start and End Points
Agree on start/end events, clock source, and detection rules first. Record cold/warm/hot state, compilation/warmup, account/data state, network, display mode, temperature, and background load. Compare distributions and tails under matched boundaries rather than ranking numbers measured from different starts.
- Competitor Analysis: Use a baseline competitor device or App. Under identical conditions, how long does the competitor take from click to response?
- Regression Analysis: Compare against previous system or App versions to ensure no regression.
Take a complex app such as Taobao: at exactly what point should we call startup complete? That endpoint is not easy to settle on. Starts can also be ambiguous: physical contact, ACTION_DOWN, ACTION_UP, click callbacks, and launch requests occur at different times. Displayed is useful for its TTID definition, but does not mean all content is loaded. onWindowFocusChanged() reports focus changes, not completion. For user-required content, define a verifiable ready condition and corroborate it with markers, automation, or optical measurements.
Common Responsiveness Issues
Android System Issues Causing Slowness
These are possible resource or cross-process dependencies. Thread states guide investigation; they do not assign responsibility. The same symptom can originate in the app, a service, or shared-resource contention.
| Observation | Possible contributors | Further evidence |
|---|---|---|
| Long Running | More work, frequency/core capacity, cache/memory behavior, driver execution | Comparable-work stacks, topology/residency, frequency/limits, available hardware counters |
| Long Runnable | CPU waiting, priority/affinity/cpuset constraints, competing work | sched_switch/wakeup, allowed CPUs, priority and per-core activity; not necessarily system-wide saturation |
| Synchronous Binder wait | Remote queueing, execution, locks, nested calls | Matching transaction and server thread; the server need not be system_server |
| Sleep/lock wait | Conditions, worker/remote work, network callbacks, locks | Waiting stack, owner, and wakeup chain; the waker need not be the root cause or lock owner |
| D/Uninterruptible Sleep | Kernel waits including some I/O and other uninterruptible waits | Blocked reason, kernel stack, block/file I/O; not synonymous with low memory |
| Reduced frequency ceiling | Thermal, power, or other policy constraints | Thermal state, policy/limits, matched comparisons; low frequency alone is not an error |
| Long buffer operations | Slot availability, slow consumption, fences, drivers, Binder | Specific producer/consumer path and dependencies, not SurfaceFlinger alone |
Low memory can affect latency through reclamation, faults, compression/swap, process restarts, and I/O. Correlate memory/pressure, reclaim, fault, and lmkd events. ART’s HeapTaskDaemon and kernel kswapd perform different work, not one GC mechanism; frequent activity alone does not prove low memory. Use PSI where supported and captured; missing data is not zero pressure.
If SystemServer delays a launch, the target process may not yet exist, so this is not always an app-main-thread Binder sleep. Graphics paths also change: AOSP android-16.0.0_r1 BLASTBufferQueue manages a client-side queue and submits transactions. Not every dequeue/queue executes in an SF Binder thread.
App-Specific Issues
Inspect necessary initialization and dependencies, asking which work lies on the current response’s critical path:
Application.attachBaseContext(),onCreate(), class/static initialization, and SDK work. Measuring only onCreate misses earlier work.- Activity
onCreate → onStart → onResumeand restoration paths. Callback completion is not presentation. Default main-thread Service/BroadcastReceiver callbacks can compete with UI work, but a long callback is not automatically a system timeout. - ContentProvider initialization. In the normal AOSP android-11.0.0_r1 ActivityThread binding path, providers are installed before Application.onCreate. Initialization usually runs on main; remote data operations require analysis of their actual Binder/calling threads.
- View inflation, measure/layout/draw, or initial Compose composition/layout; not every response runs all phases. Distinguish graphics initialization and texture uploads from per-frame queue/dequeue or Surface/fence waits.
- Extra SplashActivity → MainActivity hops, repeated loading, and async data dependencies. On Android 12+, account for system SplashScreen behavior instead of adding an Activity solely for launch animation.
- Long UI Messages and waits for workers, other processes, networks, or synchronous Binder replies. Separate waiting from computation; making work asynchronous does not automatically shorten time to the user’s required result.
- WebView creation, resource access, class loading, JIT/AOT, and compilation configuration. First-run cost is not all JIT; record installation, compilation, and warmup state.
AndroidX App Startup manages initialization dependencies and supports manual initialization after disabling automatic startup for the component. It does not eliminate the underlying work. Before deferring nonessential initialization, check thread contracts, dependencies, and first-use latency so that delay is not merely shifted to the next interaction.
Analysis Routine (Mainly Systrace)
- Fix the scenario and measurement definition: Record device/system/app versions, data/account, startup state, cache/compilation, network, and thermal conditions. Define trigger, endpoint, clock, and success. Count failed/incomplete samples separately, never as zero duration.
- Capture the critical path: Use Perfetto/Systrace, relevant logs, and app trace markers. Check coverage and lost/missing events. A main-thread call chart is not whole-system evidence. Correlate cross-process IDs and align different clocks before comparing timestamps.
- Separate stages by dependency: Follow launch request, process creation, Provider/Application, Activity, first frame, and significant-content readiness. Do not sum overlapping work; improving one critical-path stage may reveal another bottleneck.
- Use states to form hypotheses: For long Running, inspect execution and resources; for Runnable, allowed CPU capacity and competition; for Sleep, dependencies; for D, the actual kernel wait. A state alone does not establish app/system responsibility. See Main Thread I/O Latency.
- Follow relevant areas:
- Kernel: Verify topology/capacity rather than assuming CPUs 0–3 are small. Below-maximum frequency is not inherently wrong, and one saturated thread does not saturate a multicore device. Use capacity-aware scheduling concepts alongside actual policy and allowed CPUs.
- SystemServer: Correlate input, launch requests, Binder, and locks. Investigate the server even before the app exists. Identify lock owners instead of labeling every sleeping Binder thread AM/WM contention.
- SurfaceFlinger: Establish the graphics path, then connect submissions, fences, composition, and presentation. Long queue/dequeue can originate in the client or driver.
- Launcher: Inspect click handling, pause, and transitions when launch comes from the home screen. Notification/deep-link launches need not involve Launcher. Animation and content preparation can overlap; do not simply add their full durations.
- Add function-level evidence when needed: Traceview is deprecated; Android Studio CPU Profiler is a replacement, not the same tool renamed. simpleperf depends on system support, symbols, and debug/profileable permissions; Android 10+ supports the documented profileable-release route. The original TraceFix link is an instrumentation example whose build-tool compatibility must be checked. Sampling and instrumentation have different coverage and overhead.
- Repeat with the same definitions and coordinate fixes: Prioritize the largest critical-path contributors, reporting sample size, percentiles, and incomplete-run rate. Vendor/app interfaces require explicit version/contract checks, not assumptions of universally available private SDKs. Some limitations may remain unresolved, or have only a small effect. Talk those through with the testers, including the evidence and the impact. Previous bug reports suggest leads, but recheck whether the current version has the same cause.
This article provides a foundation for responsiveness knowledge. It involves significant system-level details; please review the Systrace Basics Series for depth.
Series Articles
- Systrace Responsiveness in Action 1: Understanding Responsiveness Principles
- Systrace Responsiveness in Action 2: Responsiveness Analysis - Using App Startup as an Example
- Systrace Responsiveness in Action 3: Extended Knowledge on Responsiveness
- Link to Systrace Basics Series
References
- Analysis of Android App Startup Flow
- Investigation: Can App Startup Really Reduce Startup Time?
- Jetpack App Startup Explained
- App Startup Official Guide
- Complete Record of Android App Startup Optimization
- Android Application Profiling
About Me && Blog
Below is my personal intro and related links. I look forward to exchanging ideas with fellow professionals. “When three walk together, one can always be my teacher!”
- Blogger Intro: Includes personal WeChat and WeChat group links.
- Blog Content Navigation: A guide for my blog content.
- Curated Excellent Blog Articles - Android Performance Optimization Must-Knows: Welcome to recommend projects/articles.
- Android Performance Optimization Knowledge Planet: The paid community stopped operating in 2026 and no longer accepts new members; this link preserves its history.
One walks faster alone, but a group walks further together.
