CN

loading
Half a Year in the Making: Open-Sourcing an Android Internals Ebook

There is no shortage of material on Android internals. AOSP, official docs, blog posts, papers, trace discussions — it is all findable. The annoying part is that every piece speaks for a different version: this post concludes something about Android 12, that one does not say which version it tested, a third describes what happened on one particular device.

That gap is what AIW is for. The full name is Android Internal Wiki; the Chinese book title is 《Android 技术内幕:系统机制、性能优化与工具实战》 — five parts, twenty-six chapters, with the content pinned to Android 17. The repository is now public:

https://github.com/Gracker/android-internals-wiki

What the repository gives you is twenty-six chapters of content, a full table of contents, and an EPUB rebuilt every week.

Those twenty-six chapters are now far enough along to put in front of people. If you read a passage that does not match the source, an issue or a pull request is welcome.

Android Perfetto Series 18: Response Latency in Practice, from Input Events to First-Frame Feedback

This article addresses a topic easily overshadowed by startup speed and smoothness: first-frame interaction response. It asks how long the screen takes to provide the first frame of feedback after a user action. Complete page loading and stability later in an animation require other metrics.

After tapping a button, how long until its pressed state appears? After tapping a WeChat conversation, how long until the first frame of the conversation page starts moving? After swiping a list, how long until its content follows the finger? These questions relate to slow startup and dropped frames, but need their own measurement definitions.

We use Perfetto to break down this interval: from InputReader read_time, through the App receiving the event, to an associated frame’s present. This gives a candidate internal delay, estimated_input_to_present_ms. Only after confirming the target layer and that the business state visibly changed on that frame should a report call it input_to_present_ms. Neither value covers touch IC latency, delays before driver reporting, display scanning, or panel response. By the end, you should be able to define a start, endpoint, capture configuration, SQL metrics, and supplementary App markers for a tap or scroll scenario.

The article examines response latency through four independent measurements—read/dispatch, handling, ACK→first frame, and scroll responsiveness. Each comes with capture configuration, the first tracks to inspect in the UI, and SQL. It then covers five common attribution paths and the respective boundaries of high-speed cameras and Perfetto.

Android Perfetto Series 17: Domain Automation, Issue Checklists, and Platform Infrastructure

For slow camera opens, audio underruns, a stalled WebView first screen, or dropped frames in Flutter and games, the evidence is scattered across the app, system_server, cameraserver/audioserver, HAL, SurfaceFlinger, and scheduling tracks. Simply inspecting a few more tracks in the UI can easily leave critical timestamps unnoticed.

Using Camera and Audio as examples, this article describes a reusable method for domain-specific analysis: capture the right data, identify the objects, calculate stages and blocking, and preserve timestamps in the report so that reviewers can return to the UI. Camera and Audio are examples; the core is a domain schema and collaboration with platform tracing. By the end, you should at least be able to break a slow camera open into reviewable stages and an audio underrun into cycle anomalies, rather than delivering only a table of the longest slices.

Android Perfetto Series 16: GPU, Power Counters, and Hardware Bottleneck Analysis

When FrameTimeline marks a late frame but the main thread and RenderThread show no obvious long tasks, GPU work and fences are useful next checks. GPU frequency, battery current, and power rails describe hardware state in that window; they do not establish on their own why an app frame presented late.

Parts 07 and 08 covered the rendering path from the App to SurfaceFlinger; Parts 06 and 09 covered refresh rates and CPU scheduling/frequency. This article adds an often-skipped step without repeating those topics: when a problem appears to have reached the hardware resource layer, how should GPU, devfreq, battery counters, and power rails enter the analysis of the same trace interval?

These counters are difficult because not every device provides them, and different GPU vendors use different counter names. A conclusion cannot simply say “a high GPU value means a GPU bottleneck.” FrameTimeline, RenderThread, SurfaceFlinger, the GPU timeline, frequency, and power data must be examined over the same interval.

Android Perfetto Series 15: Boot Traces, Long-Running Field Traces, and Capturing Intermittent Problems

Many performance problems cannot be reproduced with a single tap. Slow boot, intermittent jank, problems after turning the screen on or off, audio interruptions after several hours, periodic stutters in an automotive system, and performance degradation as temperature rises are all poor fits for a manually recorded 10-second trace.

This article covers long-running field traces: defining the observation window in advance, using triggers to preserve the incident, ensuring the file finishes writing safely, and determining whether the collected data is trustworthy. Boot tracing is covered below as a special observation window. Part 02 already covered basic interactive capture methods—the command line, official scripts, Developer options, and the web interface. Here, we focus on what changes in the field and during long-running recording.

Android Perfetto Series 14: heapprofd and Memory Profiling

The hardest part of a memory problem is that a rising number does not immediately tell you what is growing. dumpsys meminfo provides RSS/PSS, and a Java heap dump reveals object retention relationships. But for JNI/C++, CPU-side Skia/Bitmap allocations, and native wrappers in media players, you often also need to know which call stack issued the malloc/new request.

This article covers heapprofd. Its value is bringing native allocations, frees, and call stacks into a Perfetto trace, where you can inspect them alongside application events, thread scheduling, and Binder on the same timeline.

Use heapprofd after confirming the trend. I would split the growth between native heap, graphics buffers, and other mappings with meminfo or smaps before opening a flamegraph. Otherwise, it is easy to chase a malloc stack when the growth came from GraphicBuffer. This article does not address Java object references or graphics backing memory.

We will cover when to use heapprofd, how to capture a profile, how to read it in the UI and SQL, how to interpret sampling intervals and symbolization, and finally what to check before publishing a report.

Android Perfetto Series 13: Perfetto SDK, Track Event, and App Field Tracing

A system trace can tell you when a thread ran, which CPU core it ran on, and which FrameTimeline frame missed its deadline. With Binder/ftrace/sched evidence enabled, it can also reconstruct Binder calls and clues about waiting. But it does not know which frame ID a player is decoding, which scene a game engine is loading, or how long an application task has spent in a queue.

Track Events can record decoding, texture uploads, queue depth, and cross-thread task IDs. Put them in the same window as the system tracks to find a candidate application phase, then use RenderThread, GPU, and FrameTimeline evidence to check whether it affected a visible frame.

The article follows the practical integration order: decide whether instrumentation is needed and at which layer, define an application-phase dictionary and backend, then build the minimal integration, category controls, combined system capture, and cross-thread flows. Finally, control write volume and define the app-side field tracing protocol.

Android Perfetto Series 12: Trace Dataflow and Data Loss Troubleshooting

A trace can open in the UI and return SQL rows even after data was lost during capture. If thread-state intervals are missing, process names do not line up, or Track Events have IDs but no names, first find which stage lost the data, then decide which parts of the analysis can continue.

SQL can only analyze evidence that still exists in the trace. I would not discard an entire trace just because it reports ftrace loss; first identify whether scheduling, app markers, or frame data were affected.

Part 02 covered capture, and Part 11 covered SQL queries. This article focuses on one question: where did the trace lose data, which conclusions does that affect, and how should the next capture configuration change?

We will follow the data from the kernel to the trace file, locating loss at each stage: ftrace, producer shared memory, the central buffer, incremental state, and flush. Each stage loses data differently and needs a different remedy. At the end, there is a template for explaining how much of a trace remains trustworthy in an analysis report.

Android Perfetto Series 11: PerfettoSQL, Trace Processor, and Regression Detection

Selecting a window in Perfetto UI, inspecting the main thread, RenderThread, and CPU states, then taking screenshots works well for one investigation. When I open another trace or switch devices, I want to know whether I can calculate comparable, checkable numbers for the same kind of problem.

Part 11 covers PerfettoSQL and Trace Processor. The aim is straightforward: turn judgments made in the UI into queries that others can check, then use Python to run them across multiple traces. You do not need to become a SQL expert first. Treat a trace as a set of timestamped tables, and translate your visual assessment into a query you can run repeatedly.

The article follows one path: understand Trace Processor, express an assessment as a query over a defined time window, run it from the command line, process multiple traces with Python, and finally turn the results into stable metrics and Trace Summary output. Each step includes SQL you can reuse.

SmartPerfetto Is Open Source: A Perfetto AI Assistant for Android Trace Analysis

SmartPerfetto is now fully open source. Open the repository and you can see the runnable mainline project as it exists today: the Perfetto UI fork, the agentv3 backend, MCP tools, YAML Skills, scene strategies, scripts, and documentation. There is no private core module kept outside the repository, and this is not just a thin demo shell.

The project comes from a very concrete daily workflow: you have a trace in hand, Perfetto has already exposed the facts, but moving from facts to judgment still means jumping through tables, writing SQL, matching threads, checking FrameTimeline, finding the Binder peer, and then returning to the timeline to confirm everything again. SmartPerfetto tries to turn those repeated actions into tools, so performance engineers can spend more time on judgment.

It is still in development. I am releasing it now because trace analysis grows from real samples: real devices, real vendor differences, real product traces, and real PRs all change how Skills and strategies should be written. Waiting until every capability is stable before publishing it one way would miss the stage where samples matter most.

If you often open Perfetto to inspect scrolling jank, startup, ANR, Binder, CPU scheduling, or rendering pipelines, SmartPerfetto provides a Perfetto UI with an AI Assistant. After loading a trace, you ask questions in natural language. The backend queries trace_processor_shell, invokes YAML Skills, organizes evidence, and streams conclusions plus data tables back into the browser.

Project links:

For normal trial use, you only need the main repository. Gracker/perfetto is the frontend fork used by the perfetto/ submodule. It mainly matters to developers who want to modify the AI Assistant plugin UI.

The previous two technical articles are better for readers who want the engineering details:

Those two articles go deep into the internal architecture. Once the source is public, readers usually care more about what is actually in the repository, whether it can run, and which parts are not stable yet. This article focuses on the open-source release itself: what is open, what works today, how the internal pieces are divided, how to run it locally, and where collaboration is most useful.

Android Perfetto Series 8: Understanding Vsync Mechanism and Performance Analysis

Perfetto’s vsync-app, vsync-sf, and app doFrame tracks can look like the same event. This article follows a frame request from SurfaceFlinger scheduling to the app, then relates it to RenderThread, buffers, and FrameTimeline.

The examples mainly concern 120 Hz operation. Phase settings, hardware-callback enablement, and pending frame requests affect the tracks; separate those meanings before interpreting latency.

Version note (reviewed October 2026): Java, JNI, and scheduling code are checked against android-16.0.0_r1; app/appSf roles also reference Android 13 source. Historical screenshots are not universal Android 16/17 configurations. Excerpts omit surrounding state where noted and come from different classes, not one compilable program.

Android Perfetto Series 7: MainThread and RenderThread Deep Dive

During a scrolling slowdown, the main thread may be doing layout or may already have handed drawing work to RenderThread. This article follows their hand-off, buffer submission, and SurfaceFlinger activity in Perfetto screenshots to locate waits.

The focus is the hardware-accelerated View/HWUI path. Other engines and software drawing can use different threads. FrameTimeline and presentation-side evidence are needed to determine what reached the screen.

Android Perfetto Series 6: Why 120Hz? Advantages and Challenges

120 Hz reduces the nominal refresh interval from 60 Hz’s 16.67 ms to about 8.33 ms. Display refreshes, app-produced frames, and distinct frames presented are different counts. This article uses a historical Perfetto trace to explain their relationship and the rendering/power trade-offs.

Part five covered Choreographer callbacks; here the focus is the shorter display cycle. The screenshots describe that capture, not every 120 Hz device’s scheduling configuration.

Android Perfetto Series 5: Choreographer-based Rendering Flow

This article introduces Choreographer, a class that App developers may not frequently encounter but is critically important in the Android Framework rendering pipeline. We will cover the background of its introduction, a brief overview, partial source code analysis, its interaction with MessageQueue, its application in APM (Application Performance Monitoring), and some optimization ideas for Choreographer by mobile phone manufacturers.

Choreographer coordinates pending frame callbacks with display timing; it does not itself set the screen refresh rate. At 120 Hz, the interval is about 8.33 ms. Meeting a frame deadline also depends on CPU scheduling, GPU work, buffers, and composition. Apps request callbacks as needed rather than redraw on every physical Vsync. This article also distinguishes what FrameCallback, FrameMetrics, gfxinfo, Looper, and Perfetto can observe.

Android Perfetto Series 4: Opening Large Traces via Command Line

This is the fourth article in the Perfetto series, explaining how to use trace_processor_shell to open large files exceeding 2GB locally. In actual problem analysis, we often encounter very large Trace files (greater than 2GB) that may fail to open in ui.perfetto.dev because of browser memory limits. The limit applies to memory used while parsing, not directly to the trace file’s size. In this case, we can use the official trace_processor_shell tool to open large files locally.

When I started this series, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were also migrating. Newcomers found the interface overwhelming and asked me to explain the subjects of my Systrace articles through Perfetto.

Android Perfetto Series 3: Familiarizing with the Perfetto View

The first two articles covered what Perfetto is and how to capture a trace. This third article starts after you open that trace: with so much on the screen, where do you look?

Android documentation labels Systrace a legacy tool and recommends Perfetto on Android 10+. When I wrote this article, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were migrating. This series continues the earlier analysis methods with Perfetto.

Technical review: 2026-10-14. The 2024 interface and case screenshots are retained. Updates to shortcuts and analysis semantics use official documentation and v58.3 source (11fbaed83636). The original case traces are not provided here; their illustrated wake-up chains and measurements are not new-version test results.

Android Perfetto Series 2: Capturing Perfetto Traces

The previous article Android Perfetto Series 1: Introduction to Perfetto introduced what Perfetto is. This article provides a brief introduction to Perfetto capture.

Android documentation labels Systrace a legacy tool and recommends Perfetto on Android 10+. When I wrote this article, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were also migrating. This series revisits the earlier analysis methods with Perfetto.

Technical review: 2026-10-14. The main examples target Android 12+. Original 2024 screenshots remain, with older-system and newer-UI differences explained below. Commands and configuration were checked against official documentation and script source; this update adds no new device-capture results.

Android Perfetto Series 1: Introduction to Perfetto

This is the first article in the Perfetto series. It mainly provides a brief introduction to the Perfetto tool, including its history, development, and what Perfetto can do.

Android documentation labels Systrace a legacy tool and recommends Perfetto on Android 10+. By the time I wrote this article, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were also migrating. Newcomers facing its complex interface asked me to revisit the Systrace articles using Perfetto.

Technical review: 2026-10-14. The original article and screenshots date from 2024. The updates below distinguish Android 10/11/12 data-source requirements and Perfetto v48.0/v49.0 UI changes from that earlier experience. Available data still depends on the device, recording configuration, and tool version.

Reflections on 2023: Health, Career, and the Future

I’m taking the easy way out this year and using a template to look back at the past year through several lenses: Health/Fitness, Work/Career, Friendship/Social, Personal Life/Family, Learning/Knowledge Management, Travel/Culture, Interests/Creativity, Emotions/Mental State, and Finances.

This post is more of a personal record for 2023 than a formal summary, and my writing isn’t anything special. But as I’ve realized, if you don’t record things, they slowly fade away. I hope that whenever I look back at this post, I’ll remember 2023 as a vibrant year—filled with unforgettable moments, low points, visits from distant friends, and journeys through mountains and rivers. I also want to remember the things I did poorly so I can do better next time, and to remind myself to fight the laziness that often prevents me from following through on what I know is right.

Feel free to read along and have a laugh at my expense.

Performance Considerations in Operating System Design

This article was originally written by Yingyun for my Knowledge Planet. Since the Planet has closed, I am publishing this series on OS performance design here.

Yingyun is a veteran performance optimization expert with deep insights into system-level tuning, having worked at several major smartphone manufacturers. He is currently active in our community. If you have any questions or feedback, feel free to join our WeChat group.

1. The Genesis

This starts a new series exploring the various considerations in OS architectural design. In reality, these principles apply to the design of any large-scale software.

My knowledge and experience have limits, and these views are subjective. There will be gaps. I would like to hear other views and see what I have missed.

Can an App Really Do Whatever It Wants With System Permissions?

In 2023, public research described vulnerability exploitation code and dynamically delivered DEX files associated with an Android app. I wanted to see which system capabilities this code attempted to use. I put the original article together in a hurry and did not examine all the code closely. The walkthrough remains here, with corrections based on the screenshots and AOSP source. The original references follow:

  1. Deep Blue Insight: The Most “Unpardonable” Vulnerabilities of 2022
  2. XXX apk embedded privilege escalation code and dynamic delivery dex analysis
  3. History of Android Deserialization Vulnerability Attack and Defense

Security is not my specialty. For background, see History of Android Deserialization Vulnerability Attack and Defense. This article does not reproduce the exploit chain or treat an API call as proof of root access.

Systrace Thread CPU State Analysis Tips - Sleep and Uninterruptible Sleep

This is the third article in the “Systrace Thread CPU State Analysis Tips” series. It focuses on the Sleep and Uninterruptible Sleep states in Systrace—their causes, troubleshooting, and optimization. These states often represent normal waiting; investigate their conditions and dependencies when they delay a critical path.

The goal of this series is to use Systrace to view the Android system from a different perspective and to learn the Framework through visualization. While reading Framework source code can be difficult to remember, seeing the flow in Systrace can lead to deeper understanding. You can find the complete Systrace Basics and Action Series here.

Systrace Thread CPU State Analysis Tips - Running

This is the second article in the “Systrace Thread CPU State Analysis Tips” series. It analyzes the causes of the “Running” state in Systrace and provides optimization strategies for when Running segments are excessively long.

The goal of this series is to use Systrace to view the Android system from a different perspective and to learn the Framework through visualization. While reading Framework source code can be difficult to remember, seeing the flow in Systrace can lead to deeper understanding. You can find the complete Systrace Basics and Action Series here.

Systrace Thread CPU State Analysis Tips - Runnable

This is the first article in the “Systrace Thread CPU State Analysis Tips” series. It analyzes the causes of the “Runnable” state in Systrace and provides optimization strategies for when Runnable segments are excessively long.

The goal of this series is to use Systrace to view the Android system from a different perspective and to learn the Framework through visualization. While reading Framework source code can be difficult to remember, seeing the flow in Systrace can lead to deeper understanding. You can find the complete Systrace Basics and Action Series here.

Techniques, Philosophy, and Tools for Android Performance Optimization

Hackers & Painters

In his book Hackers & Painters, Paul Graham asserted, “The disparity in the efficiency of languages is becoming more pronounced, hence the rising importance of profilers. Currently, performance analysis isn’t given the attention it deserves. Many still seem to hold onto the belief that the key to accelerating program execution lies in developing compilers that generate faster code. As the gap between code efficiency and machine performance widens, it will become increasingly apparent that enhancing the execution speed of application software hinges on having a good profiler to guide program development.” by Paul Graham, Hackers & Painters

Search for “Android optimization tools” and you’ll find plenty of articles. Many repeat the same material or go straight to instructions without explaining how the tools fit together. It is easy to come away thinking one tool can solve everything. Our team’s experience says otherwise: there is no silver bullet. Tools change, and familiar problems return in new forms. You still need to understand what is happening underneath.

We’ll start with the data we collect, how we collect it, and how we analyze it. Then we’ll look at Google’s traditional “big three” performance tools. We want you to understand the measurements as well as the tools, and save yourself some of the detours others have already taken.

Android Performance Optimization: Techniques, Methods, and Tools

Hackers and Painters

In his book , Paul Graham states: “The execution efficiency gap between different programming languages is becoming increasingly large, so profilers are becoming more important. Currently, performance profiling is not receiving enough attention. Many people still believe that the key to improving program running speed is developing compilers that can generate faster code. The gap between code efficiency and machine performance is continuously increasing, and we will increasingly clearly see that the key to improving application software running speed is having a good performance profiler to guide program development.”

By Paul Graham — Hackers and Painters

Search for “Android optimization tools” and you’ll find plenty of articles. Many repeat the same material or go straight to instructions without explaining how the tools fit together. It is easy to come away thinking one tool can solve everything. Our team’s experience says otherwise: there is no silver bullet. Tools change, and familiar problems return in new forms. You still need to understand what is happening underneath.

We’ll start with the data we collect, how we collect it, and how we analyze it. Then we’ll look at Google’s traditional “big three” performance tools. We want you to understand the measurements as well as the tools, and save yourself some of the detours others have already taken.

Android System Development Series (1): Downloading, Compiling, and Flashing Android 12

Android 12 source was released in 2021. My test phone at the time was a Pixel 3 XL. This article keeps that hands-on record and pins the release-build example to android-12.0.0_r3. Verify version mappings in the AOSP tags/build numbers table.

Compiling the code locally offers several advantages:

  1. Direct Debugging: You can flash the build onto a physical device for local debugging and import the code into Android Studio.
  2. Userdebug Builds: These provide additional debugging capabilities. adb root/remount still depends on adbd, AVB/verity, partition layout, and build configuration. A userdebug build does not make every directory writable or replace an app’s own debugging permissions.
  3. Studying the System: You can enable more system debug logs, add your own, and change the code to see how it works.
Android Systrace Responsiveness in Action 2 - Responsiveness Analysis - Using App Startup as an Example

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.

Android Systrace Responsiveness in Action 1 - Understanding Responsiveness Principles

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.

Android Systrace Smoothness in Action 3 - FAQs During Jank Analysis

Different people have different understandings of smoothness (jank/dropped frames) and different perceptions of jitter thresholds. Therefore, before starting this series, it is necessary to clarify the content to avoid misunderstandings. Here are some basic explanations:

  1. For mobile users, jank encompasses many scenarios: dropped frames when scrolling lists, excessive white screen during app startup, slow screen wake-up when pressing the power button, unresponsive interface followed by a crash, no response when clicking an icon, incoherent window animations, lagging touch response, or stuttering when entering the desktop after a reboot. These scenarios differ slightly from what developers understand as “jank.” Developers categorize these more finely, which is a cognitive gap between developers and users that must be noted when handling feedback from users or testers.
  2. Developers can initially classify feedback as Smoothness (uneven visual progress), Responsiveness (long waits after an action), or Stability (crashes and ANRs). These can overlap. An icon that appears unresponsive is not necessarily a stability failure; input, application state, and logs determine the diagnosis.
  3. These are not one Message-timeout mechanism with different thresholds. Long main-thread tasks can delay both input and rendering, but GPU work, SurfaceFlinger, the display stack, scheduling, or remote services can also cause delays. ANRs depend on specific input or component timeout rules; crashes have separate causes such as exceptions or signals. A long Message alone establishes neither.
  4. This series primarily analyzes smoothness-related issues. Responsiveness and stability will be covered in dedicated articles. Understanding smoothness first will make analyzing responsiveness and stability much easier.
  5. This series focuses on using Systrace (Perfetto) for analysis. Systrace is our entry point because many factors affect smoothness—some within the app itself and others within the system. Systrace (Perfetto) provides a holistic view of the system’s operation during the problem, helping us initially pinpoint the root cause.
Android Systrace Smoothness in Action 2 - Case Analysis - MIUI Launcher Scroll Jank Analysis

Different people have different understandings of smoothness (jank/dropped frames) and different perceptions of jitter thresholds. Therefore, before starting this series, it is necessary to clarify the content to avoid misunderstandings. Here are some basic explanations:

  1. For mobile users, jank encompasses many scenarios: dropped frames when scrolling lists, excessive white screen during app startup, slow screen wake-up when pressing the power button, unresponsive interface followed by a crash, no response when clicking an icon, incoherent window animations, lagging touch response, or stuttering when entering the desktop after a reboot. These scenarios differ slightly from what developers understand as “jank.” Developers categorize these more finely, which is a cognitive gap between developers and users that must be noted when handling feedback from users or testers.
  2. Developers can initially classify feedback as Smoothness (uneven visual progress), Responsiveness (long waits after an action), or Stability (crashes and ANRs). These can overlap. An icon that appears unresponsive is not necessarily a stability failure; input, application state, and logs determine the diagnosis.
  3. These are not one Message-timeout mechanism with different thresholds. Long main-thread tasks can delay both input and rendering, but GPU work, SurfaceFlinger, the display stack, scheduling, or remote services can also cause delays. ANRs depend on specific input or component timeout rules; crashes have separate causes such as exceptions or signals. A long Message alone establishes neither.
  4. This series primarily analyzes smoothness-related issues. Responsiveness and stability will be covered in dedicated articles. Understanding smoothness first will make analyzing responsiveness and stability much easier.
  5. This series focuses on using Systrace (Perfetto) for analysis. Systrace is our entry point because many factors affect smoothness—some within the app itself and others within the system. Systrace (Perfetto) provides a holistic view of the system’s operation during the problem, helping us initially pinpoint the root cause.
Android Systrace Smoothness in Action 1 - Understanding Jank Principles

Different people have different understandings of smoothness (jank/dropped frames) and different perceptions of jitter thresholds. Therefore, before starting this series, it is necessary to clarify the content to avoid misunderstandings and help everyone approach these articles with the right questions. Here are some basic explanations:

  1. For mobile users, jank encompasses many scenarios: dropped frames when scrolling lists, excessive white screen during app startup, slow screen wake-up when pressing the power button, unresponsive interface followed by a crash, no response when clicking an icon, incoherent window animations, lagging touch response, or stuttering when entering the desktop after a reboot. These scenarios differ slightly from what developers understand as “jank.” Developers categorize these more finely, which is a cognitive gap between developers and users that must be noted when handling feedback from users or testers.
  2. Developers can initially classify feedback as Smoothness (uneven visual progress), Responsiveness (long waits after an action), or Stability (crashes and ANRs). These can overlap. An icon that appears unresponsive is not necessarily a stability failure; input, application state, and logs determine the diagnosis.
  3. These are not one Message-timeout mechanism with different thresholds. Long main-thread tasks can delay both input and rendering, but GPU work, SurfaceFlinger, the display stack, scheduling, or remote services can also cause delays. ANRs depend on specific input or component timeout rules; crashes have separate causes such as exceptions or signals. A long Message alone establishes neither.
  4. This series primarily analyzes smoothness-related issues. Responsiveness and stability will be covered in dedicated articles. Understanding smoothness first will make analyzing responsiveness and stability much easier.
  5. This series focuses on using Systrace (Perfetto) for analysis. Systrace is our entry point because many factors affect smoothness—some within the app itself and others within the system. Systrace (Perfetto) provides a holistic view of the system’s operation during the problem, helping us initially pinpoint the root cause.
Why is the Weibo Experience Better on Huawei? A Technical Analysis and Reflection

A fellow developer shared a Weibo post (https://weibo.com/1808884742/IApbpEVQr) where blogger @王波粒 noticed a peculiar phenomenon on the Mate 30 Pro. I highly recommend watching the video first.

The question concerns a difference observed in 2020: some Huawei samples displayed feed images during scrolling, while some other samples waited until the list stopped. This is not a claim about every current device; configuration, caches, and system behavior can differ even with the same client version.

The same version of Weibo behaving differently on different phones was something I wanted to understand as a system performance engineer. Had Weibo made a specific adaptation? What had changed? Let’s look at the code and see what we can learn.

An Incident Caused by a 'Leap' Month - Analysis of Samsung System Reboots

Around 1:30 AM on May 23, 2020, a large number of Samsung phone users in China experienced severe issues including freezes, infinite reboots, and forced entries into Recovery Mode. Improper handling by users led to data loss, and the incident quickly became a trending topic on social media platforms like Zhihu, with service centers overwhelmed.

Social media responses ranged from frustration to anger, with some comparing the incident to the Note 7 battery disaster, “charging-gate,” or “green-screen-gate.” Some predicted Samsung would be forced out of the Chinese market. People lost job offers due to missed calls, others lost valuable data, and some even resorted to smashing their devices in frustration.

As an Android developer, I am not here to pile on Samsung. My goal is to uncover the root cause of this incident and see what we can learn from it. Since it’s a technical failure in the Android system, it’s essential to analyze it from a technical perspective.

Analysis of Android App Chain Wakeups

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?

Android Systrace Basics - SurfaceFlinger Explained

This is the fifth article in the Systrace series, primarily providing a brief introduction to the workflow of SurfaceFlinger. It covers several important threads within SurfaceFlinger, including Vsync signal interpretation, app buffer display, and jank detection. Since Vsync has already been covered in Systrace Basics - Vsync Explained and Detailed Explanation of Android Rendering Mechanism Based on Choreographer, it won’t be discussed in detail here.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - CPU Info Interpretation

This is the twelfth article in the Systrace series, primarily providing a brief introduction to the CPU information area (Kernel) in Systrace. It covers how to view CPU-related information output by the Kernel module, including CPU frequency, scheduling, frequency locking, and core locking.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Triple Buffer Explained

This is the eleventh article in the Systrace series, providing a brief introduction to Triple Buffer within Systrace. It covers how to identify jank in Systrace, perform preliminary localization and analysis, and explains the impact of Triple Buffer on performance.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Binder and Lock Contention Explained

This is the tenth article in the Systrace series, primarily providing a brief introduction to Binder and lock information in Systrace. It covers the basic situation of Binder, the representation of Binder communication in Systrace, how to view Binder information, and analysis of lock contention in SystemServer.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Vsync Explained

This is the seventh article in the Systrace series, primarily introducing the Vsync mechanism in Android. This article examines the display of each frame in the Android system from the perspective of Systrace. Vsync is a critical mechanism in Systrace. Although invisible and intangible when operating a phone, we can see in Systrace how the Android system, guided by Vsync signals, orderly performs rendering and composition for each frame, ensuring stable frame rates.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Complete Guide to Android App Startup Optimization

I’ve gathered the Android app startup optimization approaches I knew of when writing this article. Use them as a checklist: see what others have tried, then look for gaps in your own app. The details depend heavily on your business, so I won’t explain every implementation here. Once you find an approach that fits, follow up on that particular method.

I’ve also included some startup work done by system manufacturers, limited to the parts I know about. There are proprietary tricks I can’t cover here. Knowing what happens on the system side may still help, including when discussing whitelisting or SDK integration with a manufacturer.

Comprehensive Record of Android App Startup Optimization

I’ve gathered the Android app startup optimization approaches I knew of when writing this article. Use them as a checklist: see what others have tried, then look for gaps in your own app. The details depend heavily on your business, so I won’t explain every implementation here. Once you find an approach that fits, follow up on that particular method.

I’ve also included some startup work done by system manufacturers, limited to the parts I know about. There are proprietary tricks I can’t cover here. Knowing what happens on the system side may still help, including when discussing whitelisting or SDK integration with a manufacturer.

Android Systrace Basics - MainThread and RenderThread Explained

This is the ninth article in the Systrace series, primarily introducing the MainThread and RenderThread in Android Apps—commonly known as the Main Thread and Rendering Thread. This article examines their workflows from the perspective of Systrace and covers related topics: jank, software rendering, and dropped frame calculation.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Input Interpretation

This is the sixth article in the Systrace series, primarily providing a brief introduction to Input in Systrace. It covers the Input workflow, how Input information is represented in Systrace, and how to combine Input info to analyze related performance issues.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Analysis of 'Zombie Animations' in the Android Background

This article records a 2019 issue: animation work continued after the app’s UI was no longer visible. However, some apps continue to run “zombie animations”—animations that are completely invisible to the user yet consume precious CPU cycles and battery. When users discover this, the result is often a manual kill, an OS-level background restriction, or an outright uninstallation.

This issue can be easy to miss. In the original investigation, I used Systrace after opening apps and returning home, capturing traces while swiping between launcher pages. Some departed apps still fired callbacks. A reproduction should record versions, operations, and visibility; opening many apps is not itself a diagnostic requirement or proof.

Here, “zombie animations” means updates that continue when their UI is invisible and the feature no longer needs them. Many paths can schedule animation work through Choreographer. Investigate the actual stack, playback state, and library version. A live process is not necessarily free to consume CPU indefinitely; modern systems can freeze eligible cached processes.

Detailed Explanation of Android Rendering Mechanism Based on Choreographer

This article introduces Choreographer, a class that app developers rarely encounter but is crucial in the Android Framework rendering pipeline. It covers the background of Choreographer‘s introduction, an overview, source code analysis, its relationship with MessageQueue, its use in APM, and optimization ideas from mobile manufacturers.

Choreographer coordinates animations, some input processing, and View updates with display timing. It requests frame callbacks when work is pending rather than unconditionally waking the app on every physical refresh. A 60Hz display, common in 2019, has an interval of about 16.67ms; 90Hz and 120Hz correspond to about 11.11ms and 8.33ms. Modern devices can also change refresh rates. A timely callback does not mean the image has been presented: RenderThread, GPU, composition, and display work remain. Understanding this flow helps explain Message, Handler, Looper, MessageQueue, Measure, Layout, and Draw.

Overview of Jank and Frame Drops in Android - Low Memory

In the Overview of Jank and Frame Drops in Android - System Layer article, we touched upon jank cases caused by low system memory. Since low memory has a significant impact on overall device performance, I’m dedicating this article to exploring those effects in depth.

As Android versions evolve and apps become more feature-heavy, their memory requirements increase. When this article was written in 2019, many devices had 4GB of RAM or less. These users are prone to low memory situations, especially after major system updates or as more apps and services run concurrently.

Memory pressure can contribute to slow responsiveness and jank. Examples include longer app launch times, more frame drops in scrolling, more frequent cold starts as background processes are killed, and extra reclaim/restart work that can increase power use. Heat alone does not diagnose memory pressure. Below, I’ll outline the causes, debugging methods, and potential optimizations for these issues.

Case Study: Debugging the Android Launcher Kill Problem

This started with a bug I encountered at work. It was not a difficult one, but while writing my diary afterward, I thought the investigation was worth recording and sharing. I also learned some useful analysis and tool tricks from my clever colleague Mei Ming.

I’ve used a variety of tools mentioned in my Android Performance Optimization Methodology, including:

  • Reproduction Video
  • Event Log
  • AS Source/Debug
  • AS Profiler
  • Systrace
  • Dumpsys
  • Unix ps utility

You might wonder whether such a simple bug needs an article. I wanted to keep a record for myself, and the way we used the tools together may be useful in other investigations. If it helps you, all the better. If you have your own debugging tricks, please join our discussion group and share them!

Overview of Jank and Frame Drops in Android - Application Layer

Technical review · 2026-10-13. The original 2019 images, thread listing, and author observations are retained. Technical checks use AOSP android-9.0.0_r1 and android-16.0.0_r1, with current entry points including API 31 frame timing and DataStore 1.2.1. The screenshots are not measurements of current app releases; no original-device or complete-trace reproduction was performed.

In the Overview of Jank and Frame Drops in Android - System Layer article, we listed causes of jank originating from the system. In this article, we focus on causes stemming from the App itself. When you encounter lag, before blaming the phone manufacturer, consider if it’s the App’s own inefficiency.

OEM and app teams may use Matrix or their own monitoring. System access can reveal more evidence, but coverage still depends on build, capture configuration, and platform support.

Average FPS alone does not describe smoothness. Two periods averaging 55 FPS can have different frame intervals and pauses. Consider intended cadence, actual presentation, and input response rather than using a change from 60 to 55 as a diagnosis. This four-part series includes:

Overview of Jank and Frame Drops in Android - System Layer

Technical review · 2026-10-13. These cases and screenshots date from 2019. The review uses relevant Android 8.1/9/16 source, Linux v6.6 documentation, and current Android documentation while preserving the images and the author’s experience. Long slices, CPU numbers, reclaim activity, and input pacing are no longer treated as standalone proof of root cause. No original-device rerun or complete trace replay was performed, and missing conditions are not invented.

The Application Layer article covers app-side problems. Here we organize cases around system services, display, scheduling, and memory. Hardware, kernels, and vendor implementations differ, so retain the actual system version and configuration.

OEM and app teams may use Matrix or their own monitoring. System privileges can expose more evidence, but capture scope still depends on build type, kernel configuration, and enabled sources.

Smoothness is not simply average FPS. An average of 55 FPS over one second on a 60 Hz display does not locate the delayed frames or determine every user’s perception. Examine intended pacing, actual presentation intervals, and input response. Static screens need not submit content on every refresh. The four-part series is:

Overview of Jank and Frame Drops in Android - Methodology

Technical review · 2026-10-13. This article retains the manufacturer’s optimization-team experience and industry opinions from 2019. The technical sections now distinguish Android 12 (API 31) FrameTimeline, JankStats, and Macrobenchmark. Looper logging was checked against AOSP android-9.0.0_r1 / android-16.0.0_r1; Matrix v2.1.0 is the documented feature baseline. No new device measurements were performed.

Jank issues in Android matter to both smartphone manufacturers and app developers. Internal performance or platform teams often investigate and optimize them.

Tools such as Tencent’s Matrix provide app-side performance evidence. Manufacturers can add their own instrumentation and use system source access and suitable debugging privileges to collect deeper data. Actual visibility still depends on the OS version, kernel configuration, build type, and enabled data sources.

Smoothness is not just average FPS. Two intervals averaging 55 FPS can contain very different frame spacing: one might include a noticeable pause, while another is more evenly paced. Consider the intended update cadence, actual presentation intervals, and input response together. Refresh intervals at 60/90/120 Hz are about 16.67/11.11/8.33 ms, but they are not fixed CPU budgets summed across every thread. A static screen need not submit new content on every refresh.

Causes can lie in the app, system, kernel, or display pipeline. This series has four parts:

A Detailed Guide to Activity Launch Modes in Android

Technical review · 2026-10-13. The 2019 sequences remain historical examples. Task selection, affinity, and Recents behavior were checked against AOSP android-9.0.0_r1 and android-16.0.0_r1; Android 12 (API 31) singleInstancePerTask is added below. The old records lack a complete device build identifier, and no device rerun was performed for this review.

Android Activities have several important launch modes: standard, singleTop, singleTask, and singleInstance. Plenty of articles explain these modes. I wrote a small demo to show how they change the arrangement of activities in tasks. The newer singleInstancePerTask mode is covered afterward.

Ordinary navigation within a task is commonly LIFO. Below, A -> B denotes the sequence of launch actions; task contents are listed top first. Keep an eye on the task contents after each action; following the changes makes the differences easier to see. Repeating a launch action does not necessarily create an instance. A Task is not a process or necessarily one visible Recents card.

I put the demo on GitHub too: AndroidLunchModeTest. The reviewed snapshot is eaa1f987e332e0f85187a911ad9ae01cd20fff05, using compile/target SDK 29 and min SDK 26. Its package is com.example.lunchmodetest, whereas the historical sequences below retain com.example.launchmodetest.

Check all navigation targets for each case. In the snapshot, MainActivity.startSingleTopActivity launches SingleTaskActivity, and StandardActivity launches SingleInstanceWithAffinityActivity by default. Changing one target does not implement every sequence. The WithAffinity classes actually use empty affinity; SingleTopWithAffinityActivity does not even declare singleTop. Class names are not configuration evidence. The sample code was inspected for this review; the project was not modified or compiled.

The explanations assume the same user, ordinary foreground Activity launches, and no extra Intent flags unless stated. Updating the old project to target SDK 31+ also requires explicit android:exported for components with intent filters; use true for the Launcher entry.

Android Systrace Basics - Prerequisites for Analyzing Systrace

Technical update — 2026-10-13: Historical Systrace screenshots are retained, including cases added after the original 2019 article. Colors and shortcuts refer to the legacy UI. Linux state semantics are checked against v6.6 documentation; the modern UI reference is Perfetto v58.3 (11fbaed83). Inaccurate Self Time, wakeup and scheduling-state annotations in the images are corrected in the adjacent text. These are not new device measurements.

This is the second article in the Systrace series, primarily explaining the prerequisites for analyzing Systrace. With these prerequisites, analyzing Systrace will be more effective, allowing you to identify issues faster and more efficiently.

This article introduces how to view thread states in Systrace, how to analyze thread wakeup information, how to interpret data in the information panel, and common shortcuts. By studying this article, you will gain an understanding of process and thread-related information and know how to extract key information from complex Systrace traces.

Android Systrace Basics - SystemServer Explained

Technical update — 2026-10-13: The historical screenshots and code are retained. Code excerpts were checked against AOSP android-10.0.0_r1; modern differences use android-16.0.0_r1 as an example. These tags do not identify the screenshot devices: the original traces, ROMs and build details were not supplied. The descriptions of animation ownership, StartingWindow and thread interactions are corrected below.

This is the fourth article in the Systrace series, primarily providing a brief introduction to SystemServer. It covers several important threads within SystemServer. Since Input and Binder are particularly critical, they are discussed separately and won’t be covered in detail here.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Introduction to Systrace

Technical update — 2026-10-13: First published in 2019, this article retains Systrace HTML and script workflows as historical references. Modern capture examples start from Android 11 / API 30+, with separate version requirements for app tracing APIs, permissions and data sources. Device-side atrace, host-side systrace.py and perfetto are different tools; their options are not interchangeable.

This is the first article in the Systrace series, primarily providing a brief introduction to Systrace, its basic usage, how to interpret Systrace traces, and how to analyze phenomena in Systrace in conjunction with other tools.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Why 60 FPS?

Technical update — 2026-10-13: First published in 2019, this article uses 60 Hz devices to explain frame pacing. 60 FPS is not a fixed standard for every Android device. The universal 16.67 ms budget, mismatched-rate examples and power claims are corrected below, with updated tools available from Android 11 / API 30 and Android 12 / API 31.

This is the third article in the Systrace series, explaining why 60 FPS is constantly emphasized. Here, FPS describes the app’s content frame rate, while Hz describes display refresh rate; they measure different things. For further context, refer to: A New Smooth Experience: A Talk on 90Hz.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

This article separates frame rate from refresh rate, then discusses pacing, power and response latency. On 90 Hz and 120 Hz devices, content updates still need to work with display timing, but 60 FPS and 16.67 ms are no longer universal targets.

Android Systrace -- Series Article Index

Technical update — 2026-10-13: This page is dated 2019 and retains update records from earlier tutorials. The old Systrace tooling workflow is obsolete. Read historical screenshots, source code and experiments against the Android versions stated in each article; they do not describe every current implementation. Start with the Perfetto series below for current capture and analysis workflows.

As Systrace and Android changed, my earlier tutorials started to show their age. I had also learned to read more from a trace, which helped me solve performance problems. I wanted to write those things down and get better at explaining what I had learned. If the notes helped someone else too, all the better.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Does the Android System Not Release Memory?

Besides the CPU, many users consider RAM size when buying a phone. Different RAM configurations come with different prices—but how much RAM do you actually need? How does Android manage its memory? Average users are often confused: How much RAM does this app use? How much does the system use? How does RAM affect my experience? And how much RAM should my next phone have?

A common question on Zhihu is: “Does the Android system not release memory?”. It’s not that the user doesn’t know the system releases memory, but rather they want to understand the mechanics to optimize their experience. In this article, I’ll address these user concerns. More technical details will be covered in later articles.

Some Thoughts on Android System Fluency

Version note — reviewed October 13, 2026: This article was written in 2018. Device examples, app experiences, and vendor opinions describe that period; the old hardware rankings and buying advice are outdated. Technical corrections and updates identify their Android versions. These are not new measurements of the named products.

I’ve long wanted to write about Android system fluency because it’s the most direct aspect of the user experience. The long-standing criticism that Android “gets laggier over time” still casts a shadow over the platform, and it’s a primary reason many users default to iPhone.

Because Google keeps Android open, different manufacturers produce devices with vastly different hardware, and app quality varies wildly. Consequently, fluency is affected by countless factors. It’s rarely just “the system isn’t optimized.” Often, two devices with the same OS but different SOCs offer completely different experiences.

I want to talk through some of the reasons Android can feel slow, so that the next time it happens, we don’t immediately blame the system. Perhaps uninstalling one app will turn out to be enough. Here are the areas I want to cover:

  1. Hardware
  2. System
  3. Applications
  4. The Optimization Loop

Ready? Let’s get started, and please join the discussion.

Zhihu: Save Your StartingWindow

It’s often said that the overall iOS experience is superior to Android. This is partly due to third-party software quality (iOS versions are often more polished) and partly due to Apple’s tight control over its ecosystem. To get on the App Store, you must pass rigorous reviews.

Today we look at the system-provided transition before app content is ready: Android’s StartingWindow and iOS’s Launch Screen. Neither is the same as an advertising Activity or business home screen rendered by the app.

I originally wrote that iOS required a single image. I was wrong about that. Xcode 6 release notes document XIB/Storyboard launch screens from iOS 8. They provide early feedback, not a guaranteed zero-delay timestamp. Older Android theme paths allowed customization, disabled previews, and translucent windows; behavior depends on the OS version.

Android Bottom Navigation Spec Part 2: Style, Behavior, and Dimensions

In March 2016, Google added Bottom Navigation to its design guidelines. This release was quite surprising to many, as Bottom Navigation hadn’t been mentioned in previous Material Design iterations. Bottom tab bars were common in iOS apps, while older Android guidance discouraged them. These were design recommendations, not platform limitations or a requirement for every iOS app.

This is the second article in a series on Android Bottom Navigation, covering style, behavior, and dimensions.

Android Bottom Navigation Spec Part 1: Usage

In March 2016, Google added Bottom Navigation to its design guidelines. This release was quite surprising to many, as Bottom Navigation hadn’t been mentioned in previous Material Design iterations. Bottom tab bars were common in iOS apps, while older Android guidance discouraged them. These were design recommendations, not platform limitations or a requirement for every iOS app.

This is the first article in a series on Android Bottom Navigation, covering its usage and historical evolution.

How to Calculate App Startup Time in Android?

Someone recently asked on Zhihu: “How to calculate APK startup time?”

“How can I use Python or direct ADB commands to calculate APK startup time? I want to measure the time from clicking the icon to the APK being fully started. For example, in a game, this would be from the icon tap to entering the login screen. Existing methods like adb shell am start -W provide ThisTime and TotalTime, but I’m unsure of the difference and they don’t seem to match visual reality.”

My colleague Guo Qifa and I answered different parts of the question. With his permission, I put our answers together here: partly so I could find them again, and partly to make them easier for other developers to find outside Zhihu.

Android App Launch Optimization: Implementation and Principles of DelayLoad (Part 2)

In the previous article, we tried the third DelayLoad approach. That article showed the code; here I want to follow what happens when it runs.

That takes us through several Android framework classes and Activity lifecycle methods.

I found tracing it quite fun: use the tools, add some debug code, and follow it one step at a time. Doing that helped me understand Activity startup better. I hope walking through it helps you too.

Android App Startup Optimization - DelayLoad Implementation and Principles (Part 1)

To make an Android app start faster, the main idea is to do less during startup. In practice, we usually reach for:

  1. Asynchronous Loading
  2. Delayed Loading (DelayLoad)
  3. Lazy Loading

If you have worked on startup optimization, you have probably used these already. Here I want to look at one DelayLoad implementation and why it behaves as it does. The code is simple, but following it takes us through Looper, Handler, MessageQueue, and VSYNC. I’ll also discuss the problems I ran into and some thoughts along the way.

RenderThread Workflow in Android hwui

Preface

These are my notes from learning how hwui’s RenderThread works in Android 5.0. I haven’t covered every detail; I wanted to trace the main flow so that, next time I hit a problem, I would know where to look.

I captured the first RenderThread Draw during app startup with Systrace, as shown below. It helps show the execution order on that thread, but the end of a DrawFrame slice is not the moment pixels appear on screen: GPU work, buffer consumption, composition, and presentation still matter. A StartingWindow may appear during startup; this CPU slice alone does not establish when it disappears.

Android Code Memory Optimization Suggestions - OnTrimMemory

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

onTrimMemory(int level), introduced in Android 4.0 (API 14), hints when an app should reduce unnecessary memory usage. Trimming caches can help the system retain more background processes, but does not guarantee process survival or a faster next return.

This article keeps the Q&A format to explain callback delivery, integration, and cleanup. Decide what to retain by resource purpose, and make sure the UI can recover what was released.

Android Code Memory Optimization Suggestions - Android Resources

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

I wrote this because understanding common memory problems before writing the code can save a lot of diagnosis later. We will look at Bitmaps, database queries, list reuse, and drawing: who creates each resource, what keeps it alive, and when it is no longer needed. Retention, repeated allocation, and leaks need different remedies.

Android Code Memory Optimization Suggestions - Android (Official)

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

For GC to reclaim unused objects, longer-lived owners must stop retaining references that are no longer needed. Reachability from GC roots matters, not whether another object holds a reference: a group of mutually referencing objects can still be collected when the whole group is unreachable. Becoming unreachable does not mean GC runs immediately or that the memory is immediately returned to the OS.

Memory management also includes bounded caches, resource ownership, and component lifecycles. Close files, connections, and native resources through their own APIs rather than waiting only for their Java wrappers to be collected.

Android Code Memory Optimization Suggestions - Java (Official)

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

This article covers micro-optimizations in Android Java code. Choosing suitable algorithms and data structures still comes first; these techniques are most useful for reducing repeated work and temporary allocations in hot paths.

The original source was Google’s Android Training article, Performance Tips. “Java (Official)” in the title refers to its Java coding advice for Android, not to an Oracle Java performance specification.

Enabling Multi-Window Mode on Nexus 6 with Android M

On May 28, 2015, Google announced the Android M Developer Preview for devices including Nexus 6. This records that experience; the images below show the home screen and Easter egg.

Obsolete experimental procedure · Technical review (2026-10-13): Changing system properties to expose this switch is retained only as history for Nexus 6 (shamu) and the 2015 Android M preview. Google’s later announcement identifies the initial preview as MPZ44Q, but this article retained no device build-number output to verify its exact image. Modern multi-window development uses the versioned APIs discussed at the end, without these system modifications.

Android Performance Patterns: Profile GPU Rendering

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): The three-color diagrams are retained from the 2015 video. Their Update / Execute / Process stages can be compared with Android 4.4.4 source. Android 6.0 and Android 16 use finer breakdowns and different reference-line implementations; the old legend does not apply unchanged to every device.

Original video introduction:

“If you can measure it, you can optimize it” is a common term in the computing world, and for Android’s rendering system, the same thing holds true. In order to optimize your pipeline to be more efficient for rendering, you need a tool to give you feedback on where the current perf problems lie.

In this video, Colt McAnlis walks you through an on-device tool built for this exact reason. “Profile GPU Rendering” will help you understand the stages of the rendering pipeline, see which portions might be taking too long, and decide what to do about it in your application.

Profile GPU Rendering Tool

Profile GPU Rendering is a quick on-device tool for finding operations associated with high rendering-stage costs. Despite its name, the bars do not directly measure GPU hardware execution time, and cannot identify every cause of jank on their own. See the official explanation.

Android Performance Patterns: Understanding VSYNC

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): The introduction and nine diagrams are retained from the 2015 video. The text corrects the fixed-60Hz assumption, tearing explanation, and “VSync copies the back buffer” description, and adds modern frame-rate hints and analysis tools.

Original video introduction:

Unbeknownst to most developers, there’s a simple hardware design that defines everything about how fast your application can draw things to the screen.

You may have heard the term VSYNC - VSYNC stands for vertical synchronization and it’s an event that happens every time your screen starts to refresh the content it wants to show you.

Effectively, VSYNC is the product of two components: Refresh Rate (how fast the hardware can refresh the screen), and Frames Per Second (how fast the GPU can draw images). In this video, Colt McAnlis walks through each of these topics and discusses where VSYNC (and the 16ms rendering barrier) comes from, and why it’s critical to understand if you want a silky smooth application.

Basic Concepts

To understand smoothness and jank, distinguish app frame production, system composition, and display presentation. VSync (vertical synchronization) coordinates their timing. It is not the mathematical product of refresh rate and FPS, nor an operation that renders the app’s content for it. See the AOSP VSync explanation.

Android Performance Patterns: Understanding Overdraw

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): The excerpts and diagrams are from the 2015 video. Overdraw remains a useful concept; the text now adds versioned color mappings, transparency exceptions, and conditions for removing backgrounds. Lighter overlay colors alone are not evidence of a performance gain.

Original video introduction:

One of the most problematic performance problems on Android is the easiest to create; thankfully, it’s also easy to fix.

OVERDRAW is a term used to describe how many times a pixel has been re-drawn in a single frame of rendering. It’s a troublesome issue, because in most cases, pixels that are overdrawn do not end up contributing to the final rendered image. As such, it amounts to wasted work for your GPU and CPU.

Fixing overdraw has everything to do with using the available on-device tools, like Show GPU Overdraw, and then adjusting your view hierarchy in order to reduce areas where it may be occurring.

What is Overdraw?

At the beginning of the video, the author uses a house painter as an analogy: painting a wall is hard work, and if you have to repaint it because you don’t like the color, the first layer was a waste of effort. Similarly, some drawing beneath a fully opaque region may make no contribution to the final image. When you try to balance high performance with perfect design, you often run into a common performance issue: Overdraw!

Overdraw means drawing the same pixel more than once within a frame. In the stacked-card example below, work beneath a fully opaque card may be unnecessary. Overlap is not always waste: translucent content, shadows, and antialiased edges still need the underlying color for blending. Removing that content would change the image. Clipping and renderer optimizations also affect the work performed. See the official explanation.

Android Performance Patterns: Render Performance

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): This is a study note from the 2015 video series. The Nexus 5 example and tool screenshots remain historical material. The original introduction uses 16ms as an approximation for 60Hz; the discussion below now clarifies refresh behavior, jank, and tool limitations.

Original video introduction:

Rendering performance is all about how fast you can draw your activity, and get it updated on the screen. Success here means your users feeling like your application is smooth and responsive, which means that you’ve got to get all your logic completed, and all your rendering done in 16ms or less, each and every frame. But that might be a bit more difficult than you think.

In this video, Colt McAnlis takes a look at what “rendering performance” means to developers, alongside some of the most common pitfalls that are ran into; and let’s not forget the important stuff: the tools that help you track down, and fix these issues before they become large problems.

Android Rendering Knowledge

When you think you’ve developed a world-changing app, your users might not agree. They might think your app is slow and laggy, failing to achieve the smoothness they expect, let alone changing the world. Straight into the bin! Hang on, it runs smoothly on my Nexus 5. How can it be slow? If you know anything about Android fragmentation, you’d know that many low-end phones don’t have the powerful processor and GPU of a Nexus 5, or the same clean stock Android installation.

If a large number of users complain that your app is laggy, don’t just blame their hardware. Sometimes the problem lies within the app itself, including rendering work or a blocked main thread. Measure first to identify the cause and choose a fix. Thus, knowing how Android rendering works is essential for any Android developer.

Overview of Android Performance Patterns

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

In 2015, Google introduced the Android Performance Patterns short-video series. The original playlist is on YouTube; Google’s companion-course announcement also documents the series.

Android Performance Patterns Overview

Technical review — 2026-10-13: The original 2015 motivation and viewing experience are retained. The videos remain useful background, while the old tools, Google+ resources, and fixed “16ms” guidance need the version context below.

Overdraw, VSYNC, and main-thread/RenderThread cooperation still matter, but the refresh interval is not always 16ms. It is about 16.67ms at 60Hz, 11.11ms at 90Hz, and 8.33ms at 120Hz. Use the system’s scheduling deadlines and trace data when judging actual frames instead of applying one fixed threshold to every device and scenario.

Investigation Current entry point and conditions
View / Compose hierarchy and attributes Use Layout Inspector on debuggable apps. It can also show Compose recomposition/skipping; hierarchy inspection is not a frame-duration measurement
Quick rendering-stage and overdraw signals Developer options provide Profile GPU/HWUI Rendering and Debug GPU Overdraw. The bars represent CPU-side rendering stages, not pure GPU execution time, and do not cover every custom rendering path. See the official guide
Frames missing their deadlines Perfetto FrameTimeline requires Android 12 / API 31+. Relate frames to the thread, scheduling, and SurfaceFlinger tracks actually captured
Regressions during scrolling or transitions Macrobenchmark FrameTimingMetric is available from AndroidX Benchmark 1.1.0. frameOverrunMs requires API 31+ and measures something different from frameDurationCpuMs

The old Android Device Monitor, which hosted Hierarchy Viewer and Traceview, was deprecated in Android Studio 3.1 and removed in 3.2. Use the current Profiler for method analysis and Layout Inspector for hierarchy inspection. For Macrobenchmark, follow the setup requirements: a release-like, non-debuggable, profileable target, with consistent device and scenario conditions.

Introduction quoted in the original 2015 article:

Android Performance Patterns is a collection of videos focused entirely on helping developers write faster, more performant Android Applications. On one side, it’s about peeling back the layers of the Android System, and exposing how things are working under the hood. On the other side, it’s about teaching you how the tools work, and what to look for in order to extract the right perf out of your app.

But at the end of the day, Android Performance Patterns is all about giving you the right resources at the right time to help make the fastest, smoothest, most awesome experience for your users. And that’s the whole point, right?

The videos explain Android performance in three to five minutes each. The speakers talk fast; before subtitles were available, they really tested my listening. Subtitles were available when this article was written; check each video’s current subtitle tracks rather than assuming complete coverage today.

While the videos are short, they are packed with information. A point the speaker passes over in one sentence can take a lot of reading to understand, or a while spent learning a debugging tool. This means the series doesn’t directly teach you “how to optimize your app” step-by-step; rather, it tells you what you need to know about Android performance so that you know which tools to use, what steps to take, and what goals to aim for.

Android Memory Optimization (3) - Viewing Original Bitmaps in MAT

This is the final article in our MAT series, detailing how to reconstruct original images from memory snapshots to debug leaks.

  1. Android Memory Optimization (1) - Introduction to MAT
  2. Android Memory Optimization (2) - Advanced MAT Usage
  3. Android Memory Optimization (3) - Viewing Original Bitmaps in MAT

Technical review — 2026-10-13: This historical technique depends on the Bitmap implementation. The original screenshots are retained. The field is checked against AOSP android-4.4.4_r2; Android 8.0 / API 26 explains the native-pixel change. Updated GIMP 3.2.6 import settings and a current debugging alternative follow.

When investigating image-related memory problems in MAT, knowing which image a Bitmap contains makes the object much easier to connect to an app feature. “Original image” here means the pixels held by the runtime Bitmap, not the downloaded JPEG/PNG, its compression settings, or EXIF. MAT can show what retains the object; a large Bitmap alone does not establish a leak.

This workflow requires the dump to contain the pixel array. A Java wrapper and a native address alone cannot reconstruct pixels missing from the dump.

Android Memory Optimization (2) - Advanced MAT Usage

This is the second article in our MAT series, focusing on advanced techniques for analyzing memory issues in Java and Android applications.

  1. Android Memory Optimization (1) - Introduction to MAT
  2. Android Memory Optimization (2) - Advanced MAT Usage
  3. Android Memory Optimization (3) - Viewing Original Bitmaps in MAT

Technical review — 2026-10-13: The 2015 screenshots are retained; concepts and query descriptions were checked against MAT 1.17.0 documentation. The old Studio conversion/GC menus are historical. Reference directions, unreachable-object interpretation, and leak criteria are corrected below, with missing steps restored.

For capture, see the introductory article: obtain a heap dump in Android Studio Profiler with debuggable / complete data, then export to MAT as needed. LeakCanary can support automated tests, but the ordinary leakcanary-android dependency belongs in debug builds. The official 2.14 release-analysis workflow is still marked experimental; adding LeakCanary is not a generic production-capture strategy. See UI-test integration and LeakCanary for releases.

Characteristics of Java Memory Leaks

  • A typical Java memory leak is an object that is still reachable but no longer useful.
  • Compare its intended lifetime with the actual ownership path, rather than judging only its size or instance count.
  • Recreating reusable objects adds allocation and GC work. If old objects are collected normally, that is allocation waste, not necessarily a leak. An oversized legitimate allocation can also cause OOM.

Advanced MAT Techniques

Dumping Memory with Android Studio

The screenshot shows an early Android Studio capture UI:

Historical Android Studio heap tools

Android Memory Optimization (1) - Getting Started with MAT

This is the first article in the series on using the MAT tool. This series consists of three articles, detailing how to use MAT to analyze memory issues, whether they are Java application memory issues or Android application memory issues:

  1. Android Memory Optimization (1) - Getting Started with MAT
  2. Android Memory Optimization (2) - Advanced MAT Usage
  3. Android Memory Optimization (3) - Opening Original Bitmap Images in MAT

Technical review — 2026-10-13: The tutorial and historical screenshots are retained. MAT’s heap-analysis concepts remain useful, while the Eclipse/DDMS capture workflow is obsolete. Installation requirements now reference MAT 1.17.0 (2026-06-10; Java 21+ for the standalone tool). The ART, Bitmap, retained-size, and reference explanations have been corrected.

Start with a Java/Kotlin heap dump in Android Studio Profiler, then export to MAT when its analysis is useful. LeakCanary can help find Android memory leaks. MAT mainly explains why managed-heap objects remain reachable; process-wide memory and native allocations also require tools such as dumpsys meminfo, native allocation recording, or Perfetto heapprofd on Android 10+. On user builds, heapprofd requires a debuggable or profileable app; it cannot arbitrarily profile other apps.

Introduction to MAT

What is MAT?

MAT (Memory Analyzer Tool) is an Eclipse-based Java heap analyzer. It helps us find memory leaks and reduce memory use by showing how much space objects occupy and which references keep them alive. Its reports give us places to start investigating.

image

MAT is available as an Eclipse plugin or a standalone Eclipse RCP application. The standalone tool does not require a full Eclipse IDE, but it still needs a compatible Java runtime. Whether an Android HPROF needs conversion depends on its format and the analyzer’s support, not on which MAT installation method you chose.

Android Performance Case Study Follow-up

Introduction

This is an annotated edition of Android Performance Case Study Follow-up by Romain Guy. The first-person case narrative below belongs to the original author.

Technical review — 2026-10-13: The 2015 Falcon Pro 3 / Moto X 2014 case is retained. Android Device Monitor, which hosted Tracer for OpenGL ES and Hierarchy Viewer, was deprecated in Android Studio 3.1 and removed in 3.2. The old workflow is historical; an Android 12+ Perfetto workflow is added below. The original website could not be reopened during this review; the technical corrections use the linked official documentation and versioned source.


Case study

Two years ago, I published Android Performance Case Study to help Android developers understand the tools and techniques needed to identify, track, and optimize performance bottlenecks.

That article used the Twitter client Falcon Pro as a case study. Its developer, Joaquim Vergès, was kind enough to let me use his app as an example and quickly addressed the issues I found. Fast forward to recently: Joaquim was building Falcon Pro 3 from scratch. Before its release, he contacted me about a scrolling performance issue. Once again, I had to analyze it without access to the source code.

Android Tips Round-Up, Part 5

In the original Chinese post, I translated Dan Lew’s fifth and final Android tips round-up, which he published in May 2014. As in the earlier parts, I added explanations and notes of my own rather than translating word for word. I hope a few of these tools save you some trouble. Technical corrections and version updates are noted below.

Technical review — 2026-10-13: Old Support Library links now point to AndroidX. Storage, thumbnail generation, and app languages have version-specific updates. The side effects of clearing app data and yielding a database transaction are explained in their entries.

Android Tips Round-Up, Part 4

In the original Chinese post, I translated Dan Lew’s fourth Android tips round-up, which he published in May 2014. These are small tools worth sharing, and I added my own notes where I had something to contribute. The version updates are noted below.

Technical review — 2026-10-13: Most of these View/XML APIs remain usable, but the explanations of configuration changes, clipping, and atomic files needed correction. The Gradle Daemon has been enabled by default since 3.0. AtomicFile behavior is illustrated using Android 4.4.4 and Android 16 source versions below.

Android Tips Round-Up, Part 3

In the original Chinese post, I translated Dan Lew’s third Android tips round-up, which he published in April 2014. As with the earlier parts, I added my own notes and explanations where I thought they would help. Some of these are tools I use myself; if a few are new to you, I hope they come in handy. The API corrections and version limits are noted below.

Technical review — 2026-10-13: Platform android.app.Fragment was deprecated in API 28; the Fragment entries below use AndroidX. LocalBroadcastManager and Otto are no longer maintained. Other tips remain useful within the API and behavior limits stated below.

Compiling Android Lollipop Firmware for Nexus 5

Technical review — 2026-10-13: This is a historical Nexus 5 / Android Lollipop tutorial with an obsolete device and toolchain. Its LRX22C binaries correspond to Android 5.0.1 / AOSP android-5.0.1_r1. The source, binary, and flashing requirements below are tied to that combination. An Android 16 Cuttlefish example is added separately; do not mix it with the old phone firmware.

Following my previous article, Using Android Studio to View Android Lollipop Source Code, we know that simply reading code has its limits—understanding can remain superficial and easily forgotten. In contrast, code you’ve personally written or modified tends to leave a much deeper impression, and the process becomes easier to grasp during the implementation phase. While studying the source code, being able to modify it, run it on a phone, and see the results firsthand significantly boosts both learning efficiency and enthusiasm. This article explains how to compile the Android Lollipop source code yourself and run it on a Nexus 5.

Why compile your own firmware instead of using Google’s factory images?
The goal here is a userdebug build suitable for platform debugging. User builds restrict facilities such as ADB root. Userdebug enables more debugging operations, but does not make every partition freely writable under all conditions.

This guide assumes a consistent Lollipop source tree and a Nexus 5. See the historical AOSP environment guide and source download instructions. Android 5.x uses OpenJDK 7 on Linux. Keep its old OS and dependencies in a dedicated historical build environment rather than using it as the setup for a current workstation.

AOSP means Android Open Source Project. It includes the platform and open-source apps, but not the proprietary Google Mobile Services (GMS) suite. Hardware binaries, GMS licensing, and Android compatibility are separate matters. Meeting the CDD and passing CTS establishes compatibility; it does not automatically grant GMS. For the requirements, see the Android compatibility overview.

Android Performance Optimization - Introduction to Systrace (Part 1)

Technical review — 2026-10-13: This article was written in 2015. Its event-timeline concepts remain useful, while the Eclipse / Device Monitor entry points are obsolete. Historical script options below are checked against AOSP android-5.0.0_r1. The added Perfetto commands target Android 11 / API 30 and later, with older-system differences noted separately. Continue with the Android Perfetto series catalog.

Old workflow Current counterpart
Systrace button in Eclipse / Device Monitor On-device System Tracing from Android 9 / API 28, or capture through ADB
systrace.py calls atrace and produces HTML Perfetto records a binary trace, with events selected by categories or a config file
Open the old HTML directly in a browser Import the trace into Perfetto UI, or analyze it with Trace Processor SQL
Assume user builds cannot trace User builds can record system traces; available data depends on the OS, data source, app configuration, and vendor policy

This is the first article in the Android Performance Optimization Tools series. This series mainly introduces the tools used during the Android performance optimization process, how to use these tools to discover problems, and how to solve them. In terms of performance optimization, Android provides many performance tools for everyone to use. Following our consistent “discover problem - solve problem” thinking, discovering the problem is the most important part. Trying to solve a problem without first identifying it properly often leads to twice the effort for half the result.

In this article, we’ll start with a brief introduction to the Systrace tool.

Introduction to Systrace

Systrace arrived with Android 4.1 / SDK Tools R20 as a system-event tracing and visualization tool. It places enabled CPU scheduling, SurfaceFlinger, WindowManager, View, and other events on a shared timeline. It does not automatically sample every Java method or provide complete call stacks. See the original SDK Tools R20 announcement.

The historical workflow has three parts:

  • Kernel events: These depend on enabled ftrace support and accessible kernel events. Scheduling, I/O, frequency, and other categories must be checked on the device.
  • Userspace annotations and collection: System components emit ATrace markers, while atrace configures categories and reads tracing data. Apps can add their own sections with android.os.Trace.beginSection() / endSection(); these public APIs were added in Android 4.3 / API 18, not Android 4.1.
  • Host-side reporting: The old systrace.py invokes atrace over ADB, processes the data, and builds an HTML report with a viewer. Existing system events can be captured without changing app code; custom business-operation sections require instrumentation.

Perfetto supports additional data sources, so describing all of it as an ftrace wrapper would be incomplete. It still reads android.os.Trace markers. See the Trace API and Perfetto ATrace documentation.

Viewing Android Lollipop Source Code with Android Studio

Technical review — 2026-10-13: The original article targets Android 5.0 Lollipop and Android Studio 1.x. The historical IDEGen workflow below has been checked against AOSP android-5.0.0_r1; the added AIDEGen example uses the documentation at android-16.0.0_r1.

Android Studio

Google has always looked after its own. The Nexus 5 got Android 5.0 right away, and Android Studio was getting plenty of attention too. I switched from Eclipse early on and followed Android Studio from the betas through to 1.0.

Android Performance Optimization: Overdraw - Practical Application

Introduction

The previous article covered the theory of overdraw and tools to detect it. While iOS users rely on Apple’s curation, Android users rely on developers’ discipline. Unfortunately, many market-leading Android apps still suffer from significant overdraw issues. As a developer, I want to see Android bridge and eventually surpass the experience gap with iOS.

This post follows one overdraw optimization case. It uses only a few of the available techniques; apps differ, and so will the changes they need. Treat it as an example. Getting this right still takes work.

If you missed the theory part, check it here: Android Performance Optimization: Overdraw (Part 1)


Android Performance Optimization: Overdraw - Theory

Updated 2026-10-13: This article was written in 2014. Its source excerpts have been checked against AOSP android-4.4.4_r2. Overdraw remains relevant, but ADT, monitor, Hierarchy Viewer, and the old OpenGL tracing workflow are outdated. Android Studio 3.1 and later use Layout Inspector for hierarchy inspection; use Perfetto for frame timing. The historical source is retained below, with Android 12 and Android 16 boundaries added.

It’s been a while since my last update. After joining a new company, things have been busy, but I’ve been spending a lot of time researching Android performance. I’ve realized there’s so much I still don’t know, so I’m starting from the application level and working my way down. This series will document my learnings on Android performance optimization.

First, we’ll discuss GPU Overdraw, which is often the most direct point of contact for developers. This topic is split into two parts: Part 1 covers the theory and optimization suggestions, and Part 2 will walk through a practical optimization example.

What is Overdraw?

GPU overdraw means drawing the same pixel more than once within a frame. For example, drawing a TextView background and then its text can draw the pixels under the characters twice. Extra shading, blending, and memory accesses cost resources, but whether they cause missed frames depends on area, transparency, GPU capabilities, and the rest of the frame’s work. A color overlay alone cannot establish the performance impact. See Android’s overdraw guide.