First article in the Building ArjunaOS series. We talk about what custom ROMs really are, why we chose LineageOS as our base instead of raw AOSP, and what you will need to follow along.
I have been working with Android platform code for a while now, and one question keeps coming up in forums, Discord servers, and even in DMs: "How do I actually build my own custom ROM?"
Most of the tutorials out there either skip too many steps or they just dump a bunch of commands without explaining what is happening behind the scenes. You follow along, something breaks at step 7, and you have no idea why because you were just copy-pasting.
This series is going to be different. We are going to build a complete custom Android OS called ArjunaOS, based on LineageOS, and I am going to explain the why behind every step, not just the what.
By the time we are done, you will have a working Android OS running on an emulator with custom branding, a custom boot animation, your own system apps, and even a weather system service integrated into the notification shade. And because of how we structure everything, the same code works on real devices too.
Hold on, what even is a custom ROM?
If you have been around the Android community, you probably already know this, but let me quickly cover it for people coming from app development or other backgrounds.
ROM stands for Read-Only Memory. In early Android days, the system partition was literally read-only, and when people talked about replacing it, they called it "flashing a ROM". The name stuck even though modern Android does not really work that way anymore.
So when someone says "I am running a custom ROM", what they mean is they replaced the stock operating system on their phone with a modified version that someone built from source code.
Think of it like Linux distributions. You have the Linux kernel, and then Ubuntu, Fedora, Arch, Mint all take that same kernel and build different experiences on top. Same idea with Android. Google releases the Android Open Source Project (AOSP), and then LineageOS, PixelExperience, crDroid, Evolution X and dozens of others take that base and add their own features, designs, and tweaks.
Coming from app development? Building a ROM is a completely different world. Forget Android Studio. You will be working with makefiles, shell scripts, and a build system that compiles everything from the Linux kernel all the way up to the calculator app. The source code is around 100-200 GB and a full build takes hours. It is a different kind of development entirely.
Why LineageOS and not raw AOSP?
This comes up every single time and I want to address it clearly.
AOSP is what Google puts out as open source. It is the foundation of Android, but that is literally all it is. A foundation. If you try to build AOSP right now and flash it on your phone (assuming your phone is even supported, which it probably is not), you will get a very bare experience. No real privacy controls, limited quick settings, no call recording, and most importantly, very few devices are supported out of the box.
LineageOS takes AOSP and does the heavy lifting for you:
- Supports 300+ devices with proper hardware integration
- Ships monthly security patches
- Adds features that users actually expect (Privacy Guard, LiveDisplay, customizable quick settings)
- Has a build infrastructure that is battle-tested and well documented
Here is the thing that a lot of beginners do not realize: almost every popular custom ROM out there is built on top of LineageOS, not AOSP directly. PixelExperience, crDroid, Evolution X, they all use LineageOS as their base. There is a good reason for that. Why rebuild device support and security infrastructure when someone already did it well?
So we are going the same route. We build on LineageOS and spend our time on the parts that make ArjunaOS unique.
What this series covers
This is not going to be a quick 3-article thing. Building a proper custom ROM involves a lot of moving pieces, and I do not want to rush through any of them.
The series is split into three parts:
Part 1: Building the OS (what we are starting now)
This first part is about 14 articles. We go from understanding the architecture and setting up your build environment, all the way to having a fully branded, packaged ArjunaOS build. Here is a rough overview:
- Understanding how LineageOS and its repo system works
- Setting up your Ubuntu machine for Android development
- Syncing source code (this alone takes a few hours depending on your internet)
- Making your first build and booting it on an emulator
- Learning the build system properly so you are not just running commands blindly
- Rebranding everything from LineageOS to ArjunaOS
- Creating a custom boot animation
- Building system apps that ship pre-installed
- Using Runtime Resource Overlays for theming
- Adding custom entries to the Settings app
- Setting up a clean vendor overlay layer
- Final build, testing, and packaging
That last point about the vendor overlay layer is really important. It is the technique that lets you keep all your changes separate from LineageOS code, so when a new version comes out, you can update without losing anything. We will talk about this more in later articles.
Part 2: System Services and UI Customization (future)
Once we have a solid, bootable OS, we start adding real features. The main project here is building a weather forecast system service that runs at the framework level and integrates with the Settings app, notification shade, and lockscreen. We will also add other basic features that demonstrate how to properly extend Android at the system level.
Part 3: Advanced Customization (future)
The advanced part. Topics here will partly depend on what readers find most useful from Part 1 and 2. We will cover deeper framework modifications, performance tuning, and more complex system-level features.
Each article builds on the previous one, so you cannot really skip ahead. But I am going to show real file changes, actual terminal output, and the exact commands. When something breaks (and it will break, trust me), we debug it together instead of saying "this is left as exercise for the reader".
What you need
Let me be honest about the hardware requirements. Android platform development is resource heavy.
Your machine:
- Ubuntu 22.04 or newer (native Linux, not a VM unless you are very patient)
- 16 GB RAM minimum. 32 GB is much better. With 16 GB you will hit swap during full builds and it slows everything down significantly
- 300+ GB of free SSD space. I know this sounds crazy but the source alone is around 100 GB and the build output adds another 100+ on top. HDD will work but build times will be painful
- 8+ CPU cores. The build system parallelizes very well so more cores = faster builds
Here is what the machine I am using for this series looks like. 12th Gen i7 with 16 threads, 30 GB RAM:
lscpu on my build machine. 12 cores, 16 threads, i7-1260P.
You do not need the exact same specs, but this gives you an idea of what a real development setup looks like. If you have 16 GB RAM and 8 cores, you will be fine. It will just take longer.
Skills you should have:
- You should be comfortable with the Linux terminal. Not an expert, but you should know how to move around directories, install packages with apt, edit files with nano or vim
- Basic Git knowledge. We will use clone, commit, branch, merge, and rebase throughout the series
- Some Java knowledge helps since the Android framework is mostly Java. If you have done Android app development before, that is more than enough
Software:
- A GitHub account for tracking your changes
- Everything else gets installed in Article 3
A note on build times: Your very first full build is going to take somewhere between 1 and 4 hours depending on your hardware. I know. Coming from app development where a Gradle build takes maybe 30 seconds, this feels absurd. But after the first build, incremental builds (change one file, rebuild) usually take 5 to 15 minutes. You get used to it. Some developers I know use the build time to go make chai or review code on their other monitor.
The approach we will follow
Throughout this entire series we follow what I call the vendor overlay pattern. The idea is simple: instead of scattering ArjunaOS-owned additions across upstream LineageOS code, we group our customization layer under vendor/arjunaos/ so updates stay easier to reason about.
vendor/arjunaos/
├── config/ # Build configuration files
├── overlay/ # Runtime Resource Overlays
├── apps/ # Custom system apps
├── bootanimation/ # Boot animation files
└── sepolicy/ # SELinux policy additions
When LineageOS pushes an update, you run repo sync, and your ArjunaOS-owned changes are still sitting cleanly under vendor/arjunaos/. That means fewer chances of colliding directly with upstream framework code and less scrambling to figure out what belongs to ArjunaOS versus LineageOS.
Note: This simpler layout is intentional for the series. Vendor-side sepolicy is a valid Android 8.0+ pattern, and keeping ArjunaOS-specific work in one place makes repo management simpler while you learn. Larger production trees often split things more finely based on manifest layout, repository boundaries, and partition ownership.
We also use Git properly from day one. Feature branches, clear commit messages, the whole thing. By the end of Part 1, your Git history will tell the complete story of what ArjunaOS adds on top of LineageOS.
Coming up next
In Article 2 we dive into how LineageOS is actually structured. How the repo tool manages hundreds of Git repositories at once, what manifest files are and why they matter, how device support works internally, and how a build goes from the lunch command to a flashable zip file. Understanding this architecture is important before we start making changes, otherwise you are just poking around in the dark.
Later in the series, when we set up the ArjunaOS manifest and repo layout, we'll revisit how paths like vendor/arjunaos/sepolicy relate to manifest projects and the final checkout structure.
Article 3 after that is fully hands-on. We install all the dependencies, configure the machine, and prepare to download a lot of source code.
See you in the next one.