# The Journey of Launching An Android Activity

You're an Android developer; you know very well how to launch an Android activity and by the time you are reading this you probably did it a zillion times. But have you ever wondered why it's done this way? Why do we use intents to create an activity object? What makes an activity object unique from any other Java object? After all, it’s still a Java object, right? So, where, when, and how does the `new Activity()` statement get executed? What happens before an activity gets created? In this article, we’ll take a behind-the-scenes look at what happens when you launch an Android activity. This discussion assumes you’re familiar with Java, object-oriented programming (OOP) principles, and Android development fundamentals.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724588478151/133af26c-7cbc-416b-9116-ecf55a938e81.png align="center")

---

Let’s start by creating a project with an activity and override the default constructor. The simplest way to check the path to a constructor is by placing a breakpoint on it. It will enable us to walk through all the calls and explore the implemented code to find exactly what we want. Executing the project will result in the following:

![Android studio debugger](https://miro.medium.com/v2/resize:fit:2000/1*aQnI3GLHyaqzqs2qttJcSg.png align="center")

> *In any Unix-based operating system, the first thing the kernel does is to execute* [*init process*](https://en.m.wikipedia.org/wiki/Init)*. Init is the root/parent of all processes executing on Linux.*

As we can see at the very bottom of the debugger frames, Android internally calls something called [`ZygoteInit`](https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/os/ZygoteInit.java#70)

# What is ZygoteInit

As the name suggests, [`ZygoteInit`](https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/os/ZygoteInit.java#70) is the genesis of the Android application. It gets its name from a dictionary definition: “The initial cell formed when a new organism is produced."

Android at its core has a process called [`Zygote`](https://elinux.org/Android_Zygote_Startup), which starts at [init](https://en.m.wikipedia.org/wiki/Init). It’s a special Android OS process that enables shared code across Dalvik/Art VM. This process is a “warmed-up” process, meaning it preloads all the classes and resources that an app may potentially need at runtime into the system’s memory. It then forks itself to start a well-managed process called [`SystemServer`](https://android.googlesource.com/platform/frameworks/base/+/7d276c3/services/java/com/android/server/SystemServer.java#848) which initializes all core platform services it houses. One of the core services that gets started by `SystemServer`, which is particularly relevant here, is [`ActivityManagerService`](https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#231)**.**

![](https://miro.medium.com/v2/resize:fit:1000/0*ZkByvPGBmvH6zoMT.gif align="center")

# ActivityManagerService: Where the Magic Happens

ActivityManagerService is responsible for creating new Activity thread processes, maintaining the Activity lifecycle, and managing the activity stack. During its startup, it performs three main steps:

## 1\. **Collect Target Activity Information**

%[https://gist.github.com/Muhammadyoussef/85a44e00fdfaea874704259203a2038e] 

> [Full implementation: `ActivityManagerService.resolveActivityInfo()`](https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#3334)

The first step is to collect information about the target activity. This is done by calling `resolveIntent()` method on some hidden implementation for [`IPackageManager`](https://android.googlesource.com/platform/frameworks/base/+/483f3b06ea84440a082e21b68ec2c2e54046f5a6/core/java/android/content/pm/IPackageManager.aidl#45) interface. The target information is then saved back into the intent object to avoid redoing this step.

## 2\. **Check User Privileges**

%[https://gist.github.com/Muhammadyoussef/ec06cb6212923492050744aaed1abcb9] 

> [Full implementation: `ActivityManagerService.grantUriPermissionLocked()`](https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7388)

The next step is to check if the user has sufficient privileges to invoke the target activity. This is typically done by calling [`grantUriPermissionLocked()`](https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7388) which ensures:

1. The target package has a valid [UID](https://en.m.wikipedia.org/wiki/UID) associated with it.
    
2. The UID is used to check if the target package can grant permission to access the URI by calling [`checkGrantUriPermissionLocked()`](https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7227)
    
3. After ensuring that the caller has all the necessary permissions, [`grantUriPermissionUncheckedLocked()`](https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7360) grants them to the target package.
    

![](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExd2V6Nmw2Z3Y2Njg4Z3hvdjFtajhhbDJraG1zeGY2b3o3OWowY2huaCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/u65me2nV3nGlG/giphy.gif align="center")

## 3\. **Activity Object Instantiation**

Now to the juicy stuff, it’s time to check if the ProcessRecord already exists for the process. If the ProcessRecord is null, the ActivityManagerService must create a new process to instantiate the activity—duh. The instantiation is done with the help of [`ActivityThread`](https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#114) class.

At this point, all required permissions have been granted, all the information about the target activity has been stored in the intent object, and the system has made sure that the user has all the privileges to invoke the target activity. Now it’s time to instantiate and launch the target Activity. This phase can be divided into three sub-phases:

### 3.1. **Get the Environment Ready**

%[https://gist.github.com/Muhammadyoussef/b52bc0fb9bdf1bc19b1939a878c3af9e] 

> [Full implementation:](https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#1758) [`ActivityThread.handleLaunchActivity()`](https://gist.github.com/Muhammadyoussef/b52bc0fb9bdf1bc19b1939a878c3af9e#file-activitythread-handlelaunchactivity-java)

First things first, let’s get the environment ready. It does so by calling [`handleLaunchActivity()`](https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#1758)*.* This ensures that configurations are up to date, the graphics environment is initialized, and the [`WindowManager`](https://android.googlesource.com/platform/frameworks/base/+/0e40462e11d27eb859b829b112cecb8c6f0d7afb/core/java/android/view/WindowManagerGlobal.java#39) is set up.

### 3.2. **Retrieve the Previously Collected Information**

%[https://gist.github.com/Muhammadyoussef/5c9cdbc0273a7517b4d0b7d8324bb518] 

> [*Full implementation:*](https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#1640) [`ActivityThread: performLaunchActivity()`](https://gist.github.com/Muhammadyoussef/5c9cdbc0273a7517b4d0b7d8324bb518)

Next, previously collected information, such as ComponentName is retrieved, and the baseContext is created to prepare for instantiation.

### 3.3. **The Instantiation**

%[https://gist.github.com/Muhammadyoussef/6942bb7301bb9a868bfbb487879d8052] 

> [*Full implementation:*](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/AppComponentFactory.java#78) [`AppComponentFactory.instantiateActivity()`](https://gist.github.com/Muhammadyoussef/6942bb7301bb9a868bfbb487879d8052)

This is where it gets interesting. Android uses the help of [Java's reflection library](https://stackoverflow.com/a/37632/7330512) to execute the `new Activity()` statement. It does so by calling [`newActivity()`](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Instrumentation.java#1211) method on the `Instrumentation` object which then delegates the action to the`AppComponentFactory` object by calling [`instantiateActivity()`](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/AppComponentFactory.java#78) method.

![](https://miro.medium.com/v2/resize:fit:1000/0*2wSWSjnavwHXkm06.gif align="center")

After instantiation,[`ActivityThread`](https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#114) proceeds by calling [`callActivityOnCreate()`](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Instrumentation.java#1271). And this is the start of what we all know as *Activity Life Cycle* 😄

# TL;DR

> This article delves into the behind-the-scenes process of launching Android activities, exploring why intents are used and what makes an Activity object unique. It covers the role of the Zygote process, the initialization of core services by SystemServer, and the crucial functions of ActivityManagerService. The article explains how the system collects target activity information, checks user privileges, and instantiates the Activity object using Java reflection. By the end, you'll understand the detailed steps involved in the activity lifecycle from creation to launch.
