CN

Android Systrace Responsiveness in Action 2 - Responsiveness Analysis - Using...

Word count: 2.9kReading time: 18 min
2021/09/13
loading

Jank, slow response, and ANRs can share causes or occur together, but they are not three severity levels of the same problem. When a user says an app feels slow, first distinguish uneven animation, a long delay after an action, and a system-detected failure to respond.

Animation and scrolling stutter is usually called jank. Long startup, screen wake-up, or navigation delays are slow response / high latency. An ANR depends on a specific system timeout condition. Frame-drop rate, startup duration, and ANR rate measure different things.

This is the second article in the Responsiveness series, using Android App Cold Start as an example to explain how to use Systrace for analysis.

Historical case and versions (reviewed 2026-10-14): This article retains the 2021 WanAndroid startup example. Its figures include separate OPPO, Launcher3, and Meizu captures, without a complete matching device, firmware, APK version, and raw trace set. They cannot be joined into one precise startup timeline. AOSP Android 9/10/11 sources explain the older paths below; Android 12 splash screens and Android 16 startup accounting are identified separately. Where old image annotations conflict with the text, use the corrected explanation.

Table of Contents

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).

Systrace Series Articles:

  1. Introduction to Systrace
  2. Systrace Basics - Prerequisites for Systrace
  3. Systrace Basics - Why 60 fps?
  4. Android Systrace Basics - SystemServer Explained
  5. Systrace Basics - SurfaceFlinger Explained
  6. Systrace Basics - Input Explained
  7. Systrace Basics - Vsync Explained
  8. Systrace Basics - Vsync-App: Detailed Explanation of Choreographer-Based Rendering Mechanism
  9. Systrace Basics - MainThread and RenderThread Explained
  10. Systrace Basics - Binder and Lock Contention Explained
  11. Systrace Basics - Triple Buffer Explained
  12. Systrace Basics - CPU Info Explained
  13. Systrace Smoothness in Action 1: Understanding Jank Principles
  14. Systrace Smoothness in Action 2: Case Analysis - MIUI Launcher Scroll Jank Analysis
  15. Systrace Smoothness in Action 3: FAQs During Jank Analysis
  16. Systrace Responsiveness in Action 1: Understanding Responsiveness Principles
  17. Systrace Responsiveness in Action 2: Responsiveness Analysis - Using App Startup as an Example
  18. Systrace Responsiveness in Action 3: Extended Knowledge on Responsiveness
  19. Systrace Thread CPU State Analysis Tips - Runnable
  20. Systrace Thread CPU State Analysis Tips - Running
  21. Systrace Thread CPU State Analysis Tips - Sleep and Uninterruptible Sleep

1. Preparation

This case study and the corresponding Systrace are engineering-focused and omit many details, as App startup involves a vast range of knowledge. For an extremely detailed breakdown, I recommend: Complete Analysis of Android App Startup Flow.

We will follow the system trace through the major startup modules. This figure maps trace regions to phone screens. Systrace and Perfetto are different capture/analysis tools; Perfetto UI can also open older Systrace files, but their commands are not interchangeable.

Complete App Startup Visualization

Before recording, identify the launch entry point, app version, system build, cold/warm/hot state, compilation and cache state, account/network conditions, display mode, and thermal conditions. Confirm that the target app process did not exist before a cold launch. Swiping a task away does not guarantee process termination, and a cold process does not imply cold file caches or fresh app data.

  1. Capture a basic system trace first. System Tracing is available in developer options from Android 9 (API 28); it saves Perfetto format from Android 10. See the on-device capture guide. Enable available scheduling, frequency, Input, Activity/Window Manager, View/graphics, and Binder events. Cover the interval before the tap through critical content readiness. A missing track requires checking configuration, permissions, and data loss; it does not mean zero latency.
  2. Add IRQ events when needed. Availability of the legacy Systrace irq category depends on the device and permissions. Check the installed systrace.py --help and --list-categories before selecting categories. Category lists vary by device, so avoid copying an entire list without checking support. For new captures, follow the Perfetto system tracing tutorial, and examine IRQ handlers alongside scheduling of threaded interrupts.
  3. Use IPC debugging as an optional addition. am trace-ipc enables Binder tracking; it does not recover names for every native or Java IPC call. AOSP Android 11 checks caller permissions and filters non-debuggable apps on non-debuggable systems. “Requires root” and “root reveals everything” are both incomplete descriptions. Android 9 Java Binder tracking can add call stacks and some method/transaction names, with additional overhead. Start tracking before reproducing, then stop and export:
1
2
3
4
adb shell am trace-ipc start
# Reproduce the launch while the system trace is recording.
adb shell am trace-ipc stop --dump-file /data/local/tmp/ipc-trace.txt
adb pull /data/local/tmp/ipc-trace.txt

The exported file contains IPC debugging information, not a replacement system trace. If the command fails or the target process is ineligible, use the basic Binder events; missing method names do not prove no call occurred. See Android 11 ActivityManagerService and Android 9 Binder.

If you can rebuild the app, add manual Trace sections around key initialization work or use TraceFix for bytecode instrumentation. It covers selected, instrumentable methods, not system Framework or native methods, and does not guarantee a section for every function. Check the plugin’s AGP/Gradle/JDK compatibility matrix. Limit instrumentation when investigating, and control its overhead in final timing comparisons.

Without this plugin, existing Framework, system, and custom app trace points can still be visible:

Instrumentation exposes more app method sections. These figures compare visibility; they do not establish that instrumentation has no timing cost:

2. Analysis of Android App Cold Start Flow

This case follows a cold launch from the Launcher, from touch input through the launch request and process initialization to critical UI content readiness. These are participating modules, not six serial durations to add together; animations and app initialization often overlap:

  1. Touchscreen interrupt handling.
  2. InputReader and InputDispatcher event processing.
  3. Launcher input handling.
  4. SystemServer startup event processing.
  5. Startup animations.
  6. App internal startup and logic.

Choose the start explicitly: physical contact, Input Down, Input Up, the Launcher request, or system receipt of the launch Intent. Choose the end separately: initial feedback, the destination Activity’s first frame, or critical content becoming usable. TTID and TTFD cover different intervals and are not automatically physical touch-to-photon measurements. This article examines the software path; physical input-to-display timing needs separately synchronized measurement.

We’ll trace this through Systrace’s key stages:

2.1 Touchscreen Interrupt Handling

This historical figure shows a threaded interrupt named irq/382-sec_ts. It is an early software observation point, not the exact time of finger contact. Interrupt names, numbers, and touch reporting paths are device-dependent:

Touch Interrupt

The corresponding CPU scheduling and IRQ tracks follow. Scheduling exposes the interrupt thread’s execution; IRQ events expose handler intervals. They are related but distinct records:

Interrupt Zone Details

The driver reports through Linux input/evdev; EventHub reads events, InputReader interprets them, and InputDispatcher dispatches them. Interrupt counts do not map one-to-one to Java MotionEvents. The displayed 2.427 ms is a selected interval, not a measured sensor latency or the summed CPU execution time of IRQ handlers. Attribution requires wakeup, scheduling, and driver evidence.

2.2 InputReader and InputDispatcher Stage

These Native threads in SystemServer handle input events. See Input Explained for details.

InputReader and InputDispatcher

The example annotates Down, several Move events, and Up as a tap. A tap need not contain Move events, and Cancel, movement thresholds, or long-press handling may prevent a click. Verify action types in event details rather than inferring them from similar-looking slices.

After a Launcher window establishes its input channel, InputDispatcher selects targets using touch coordinates, touchable regions, window ordering, and input policy. Process creation or foreground visibility alone does not guarantee delivery of every event. The flow through SystemServer and the app is detailed in Input Explained; here are the core visualizations:

2.2.1 Event Flow in SystemServer

SystemServer Flow

2.2.2 Event Flow in Launcher

Launcher Flow

These two older figures come from a Meizu Launcher capture, not the same recording as the WanAndroid example above. A falling wq generally indicates Dispatcher has received an event-finished acknowledgment, not that a frame was presented. The second image’s aq annotation also needs correction: Android 10 ViewRootImpl decrements the pending count when removing the event, before calling deliverInputEvent. Zero pending events does not prove processing has finished.

2.3 Launcher Input Handling Stage

Inspect two intervals in Launcher handling:

  1. Down to the pressed-feedback frame: for example, dimming or shrinking the icon. Updating its state and presenting that frame are different moments.
  2. Up/click recognition to the launch request: useful for examining Launcher delay. Measuring from Down or the first feedback frame also includes the user’s hold time, which is not all Launcher processing.

Desktop swipe response time is another useful measure: physical finger movement to the first visible screen movement can be examined with synchronized high-speed footage. Cross-device comparisons require matched refresh rates, gesture speeds, content, and boundaries; software traces alone do not measure that entire physical interval.

A normal icon tap passes click recognition after Up, then requests Activity launch. From Android 10, ActivityTaskManagerService (ATMS) handles Activity/Task management in SystemServer, while AMS and related modules participate in process management. The proxy in this figure is IActivityTaskManager. Notification and deep-link launches need not pass through Launcher.

Launcher Launch Logic

This stage helps separate pre-app system/Launcher delays from app initialization. Animation coordination depends on the OS version and Launcher implementation. Icon animation, window transitions, and app preparation can overlap; slow-motion footage helps inspect continuity but cannot identify a code bottleneck by itself.

2.4 SystemServer StartActivity Stage

Focus on three kinds of work: handling the request and task/window state, coordinating existing Activity lifecycles, and requesting a target process when needed. They can interleave across threads rather than form three fixed, consecutive intervals. Multi-window and launch modes can change the path.

Processing the Launch Command

The Binder call in SystemServer is triggered by Launcher via ActivityTaskManager.getService().startActivity.

StartActivity Binder Call

When the target process is absent, it must be created before its Activity can run. In a common path, SystemServer sends a socket request to the Zygote matching the app ABI; SystemServer does not itself execute that fork. Devices need not offer both 32-bit and 64-bit Zygotes. Android 10 ZygoteProcess already includes an optional USAP process-pool path, so not every launch has an identical on-demand fork interval.

Forking New Process

Forking Code Trace

The code image calls appZygote.getProcess().start(...), an App Zygote-related branch, not a universal implementation of ordinary Activity cold starts. The 7.343 ms Start proc selection is not pure fork CPU time; it can include request construction, communication, and waiting for a result.

Zygote 64 Executing Fork

Zygote Fork

Zygote Fork Finish

This Java method writes to the Zygote socket and reads the PID/status on the caller side; it is not the function executing fork inside Zygote. Compare the ordinary request and USAP paths in Android 10 ZygoteProcess, then identify the actual path using process, thread, and scheduling evidence.

App Process Appearance

App Process in Systrace

The old ActivityThread.main screenshot shows main Looper preparation, ActivityThread construction, attachment to the system, and entry into Looper.loop. Its source points to the then-current master without a fixed commit; it illustrates the entry path but does not identify the Android version of every capture.

App Entry Code

The launching: com.aboback.wanandroidjetpack selection below is 904.966 ms. It is a system startup interval, excluding the preceding full icon press, and does not establish full content readiness. Check the recorded boundaries and destination Activity for that version. A SplashActivity → MainActivity flow does not universally stop accounting at SplashActivity: Android 16 ActivityMetricsLogger, for example, supports coalescing consecutive launches. Inspect the associated Activity and window-drawn events.

StartActivity Metrics

2.5 App Process Startup Stage

This example has a separate SplashActivity, so the following milestones help divide its startup. They are not a required architecture for every app. “UI stable” is too vague as an end condition: specify which content must be visible, which actions must work, and how errors or empty data are handled.

  1. Process Start to SplashActivity First Frame (or directly to MainActivity if no Splash).
  2. SplashActivity First Frame to MainActivity First Frame.
  3. MainActivity First Frame to Fully Loaded.

Analysis details for each:

Process Start to SplashActivity First Frame

The new process passes through runtime entry, ActivityThread.main, and attachment to the system before the system schedules work such as bindApplication. It does not jump directly from fork to app onCreate. Binding initializes a process, not every Activity launch. A process previously started for a service or broadcast may be reused when opening an Activity.

In the normal binding path in AOSP android-11.0.0_r1 ActivityThread, Application creation/attachment precedes installation of the process’s initial ContentProviders, followed by Application.onCreate. Provider initialization can therefore run before Application.onCreate, rather than all belonging to a later component phase.

A common foreground Activity creation sequence is onCreate → onStart → onResume. In this older View/HWUI example, subsequent work includes traversal measure/layout/draw, RenderThread activity, and the graphics pipeline. It is not a guarantee of one doFrame followed by one fixed Vsync interval until display: GPU, buffers, SurfaceFlinger, HWC, and the display still have their own work.

The finishDrawing marker is an app-to-WindowManager drawing notification, not a physical presentation timestamp. Android 10 ViewRootImpl sends it through WindowSession; Android 11 WindowStateAnimator can then be in COMMIT_DRAW_PENDING before later committing/showing the window. The image’s onStart/onCreate ordering should also be corrected as described above. See MainThread and RenderThread Explained for the broader pipeline.

App-side Startup Trace

SplashActivity to MainActivity

This sample transitions from SplashActivity to the main Activity. Follow its lifecycle, app initialization, WebView work, and dependencies to the destination window’s first-frame milestone. A separate SplashActivity is neither necessarily an ad nor a required launch step. From Android 12 (API 31), distinguish the system SplashScreen from an app Activity; retaining a dedicated splash Activity can produce duplicate splash screens. See the migration guide.

The 829.966 ms selection below spans the illustrated drawing-notification boundaries, not independently verified physical presentation timestamps. Whether WebView or other work delays startup depends on dependencies and waits; slice colors or lengths alone do not establish a cause.

Transition Trace

MainActivity First Frame to Fully Loaded

The main Activity’s first frame may contain only a shell, with images or list data arriving later. Define critical content readiness, mark that business event, and correlate it with subsequent drawing/presentation. An onDraw call, itemCount greater than zero, or a completed network request alone does not guarantee the user can see or interact with the finished UI.

Final Loading Trace

The 1.648 s selection marks the later loading interval chosen in the original example. Without the synchronized source recording, readiness marker, and complete trace, the final doFrame alone cannot establish full readiness. Do not add this duration to illustrative intervals from different devices.

For new measurements, retain both system TTID (initial display) and app-reported TTFD (full display). Activity.reportFullyDrawn() is available from API 19; report after the agreed critical-content/usability condition is met, not early to improve the number. Macrobenchmark StartupTimingMetric supports repeated measurements of timeToInitialDisplayMs and timeToFullDisplayMs. The latter uses the fully-drawn signal and related frame completion; it is not an arbitrary business Trace section with a different label. Missing reports or incomplete captures are separate outcomes, not zeros.

Keep the launch entry point, cold/warm/hot mode, compilation policy, and data conditions consistent. Retain each iteration’s trace and compare typical and slow samples. A faster first frame with later usable content is not an improvement in both measures.

I put together this demonstration using Systrace and phone screenshots, so you can see where each startup stage appears in the trace. The app is an open-source WanAndroid client:

Composite Visualization

End

This article focuses on visualizing the complete cold start flow in Systrace to help you locate bottlenecks and perform competitive analysis.

  1. For “How to Analyze,” see the routine in Understanding Responsiveness Principles.
  2. For “How to Optimize,” see Complete Record of Android App Startup Optimization. Optimization techniques evolve; I’ll maintain that article. If you find new techniques, leave a comment or contact me via WeChat (553000664).

Series Articles

  1. Systrace Responsiveness in Action 1: Understanding Responsiveness Principles
  2. Systrace Responsiveness in Action 2: Responsiveness Analysis - Using App Startup as an Example
  3. Systrace Responsiveness in Action 3: Extended Knowledge on Responsiveness
  4. Link to Systrace Basics Series

References

  1. Analysis of Android App Startup Flow
  2. Investigation: Can App Startup Really Reduce Startup Time?
  3. Jetpack App Startup Explained
  4. App Startup Official Guide
  5. Complete Record of Android App Startup Optimization
  6. 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!”

  1. Blogger Intro: Includes personal WeChat and WeChat group links.
  2. Blog Content Navigation: A guide for my blog content.
  3. Curated Excellent Blog Articles - Android Performance Optimization Must-Knows: Welcome to recommend projects/articles.
  4. 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.

Scan WeChat QR Code

CATALOG
  1. 1. Table of Contents
  • 1. Preparation
  • 2. Analysis of Android App Cold Start Flow
    1. 1. 2.1 Touchscreen Interrupt Handling
    2. 2. 2.2 InputReader and InputDispatcher Stage
      1. 2.1. 2.2.1 Event Flow in SystemServer
      2. 2.2. 2.2.2 Event Flow in Launcher
    3. 3. 2.3 Launcher Input Handling Stage
    4. 4. 2.4 SystemServer StartActivity Stage
      1. 4.1. Processing the Launch Command
      2. 4.2. Zygote 64 Executing Fork
      3. 4.3. App Process Appearance
    5. 5. 2.5 App Process Startup Stage
      1. 5.1. Process Start to SplashActivity First Frame
      2. 5.2. SplashActivity to MainActivity
      3. 5.3. MainActivity First Frame to Fully Loaded
  • End
  • Series Articles
  • References
  • About Me && Blog