CN

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