The directory map
Where everything lives, top to bottom: what frameworks/base actually contains, why packages/apps is not the framework, what system/core owns, and which directories are reference targets rather than platform code.
AOSP's top-level directories are a map of the platform's responsibilities, and most of them are named after what they own rather than what they do. This page is the legend.
TL;DR#
frameworks/is the platform itself:base/holds the Java framework and the system services,native/holds SurfaceFlinger and the native services,av/holds the media stack.packages/holds the system apps and providers: Settings, Launcher3, SystemUI, and the contacts and media providers. They are apps, not platform code, even though they ship with it.system/is the low-level user space:core/has init and the daemons,sepolicy/has the SELinux policy.art/,bionic/andlibcore/are the runtime and the C and Java libraries that every process uses.hardware/contains the HAL interfaces;device/andvendor/are mostly reference targets in AOSP and are where an OEM's tree takes over.
Mental model#
Think of a ship's manifest.
The engine room and hull are system/, bionic/ and the kernel-facing code. Nobody visits
unless something is wrong.
The bridge and navigation are frameworks/: the services that decide what happens.
The cabins and public rooms are packages/: what passengers see.
The shipyard drawings are build/: how the whole thing is assembled.
And the port authorities' paperwork is hardware/: the interface between this ship and the
docks it visits.
Where the analogy breaks#
On a ship, the manifest is stable. AOSP's structure has been reorganised by Treble and Mainline, so
some components that used to live in frameworks/base now live in packages/modules/ with their
own APEX. The map is accurate for the platform's shape but not always for a specific component's
location: when in doubt, search rather than assume.
The big picture#
Text description of this diagram
A treemap of the AOSP top-level directories sized by relative code weight. frameworks is the largest group, with base as its largest child, followed by native, av and libs. packages is the second group, with apps the largest child, then providers, input methods and modules. system contains core, sepolicy and helper libraries. art contains runtime and compiler. hardware contains interfaces and the legacy C HAL libraries. bionic contains libc and the linker. build contains soong and the legacy make tree. device and vendor contain reference device configurations.
Click a group in the treemap and the panel tells you what it owns. The useful exercise is to find
the directory for a component you already know: SystemUI is in packages/apps, but the window
manager it talks to is in frameworks/base/services. That split is the map's most important
lesson.
Deep dive#
frameworks/ — the platform#
frameworks/base/ is the core. It contains two things that are easy to confuse:
core/java/— the Java and Kotlin classes that make up theandroid.*API. This is what an app compiles against and what the SDK stubs are generated from.services/— the implementation of the system services, most of which run insidesystem_server.services/core/java/com/android/server/is whereActivityManagerService,PackageManagerService,WindowManagerServiceand the rest live.
The split matters: core/ defines the contract, services/ implements it. A method you call on
PackageManager is usually a facade in core/ that forwards over Binder to a service in
services/.
frameworks/native/ is C++ and holds the native services: SurfaceFlinger, the input
dispatcher, the sensor service, and the Binder libraries. When a Java service needs to draw or to
receive input, the code that does it is here.
frameworks/av/ is the media framework: codec2, the camera stack, audio, and the media
session machinery.
frameworks/libs/ holds support libraries shared across the framework: networking helpers,
HWUI (the hardware-accelerated UI renderer), and the input library.
packages/ — the system apps#
packages/apps/ contains Settings, Launcher3, SystemUI, Dialer, Camera2 and the rest. They are
ordinary APKs with privileged permissions and platform signing, and they are not part of
system_server. That distinction is why SystemUI can crash and restart without taking the system
down.
packages/providers/ contains the content providers for contacts, calendar, media and downloads.
They are where a lot of the shared data model lives, and they are a good place to read if you want
to see ContentProvider used at scale.
packages/modules/ is the Mainline tree: the components that ship as APEX modules and can be
updated without a full OS update.1 This is the directory that
changed most in the platform's recent history, and it is where the "is this part of the OS?"
question gets complicated.
system/ — the low-level user space#
system/core/ contains init, logd, adbd and the fundamental daemons. system/core/init/README.md
is the definitive description of the init language, and system/core/rootdir/init.rc is the main
configuration file that starts the system.2
system/sepolicy/ contains the SELinux policy sources. This is where the rules that confine every
process are written. It is dense and worth reading only with a specific question.
system/ also contains vold (the volume daemon), netd (networking), and the media and audio
daemons. If a process appears in ps and is not an app, it is likely started from here.
art/, bionic/, libcore/ — the runtime and libraries#
art/ is the Android Runtime: the interpreter, the JIT, the AOT compiler, the garbage
collector, and the JNI bridge. Mostly C++ with per-architecture assembly.
bionic/ is Android's C library: libc, libm, the dynamic linker. Every process links against
it. It is deliberately smaller than glibc and designed for mobile constraints.
libcore/ is the Java core library: the implementation of java.* and javax.* that Android
ships, based on OpenJDK.
These three are the parts of the platform that every app depends on and almost no app developer reads. They matter for performance, for ABI compatibility and for security.
hardware/ — the interface to the device#
hardware/interfaces/ contains the versioned HAL interface definitions: the AIDL and HIDL files
that the vendor image and the framework agree on. hardware/libhardware/ contains the older C HAL
loading mechanism.
This is the directory that Treble formalised. Before Treble, a HAL was often a shared library loaded into the framework process; after it, HALs are separate processes behind a versioned interface.3
The hidden glue: generated and overlays#
Two directories are frequently overlooked because they do not contain the code that runs.
frameworks/base/core/res/ holds the platform's own resources: the system theme, the default
strings, the drawables that system UI uses. A change here can alter every app's appearance, because
the platform resources are the fallback for every theme.
frameworks/base/packages/ holds framework packages that are not system apps in the usual
sense: the Settings Provider, the shared storage backup agent, and the framework's own overlays.
They ship with the framework rather than as separate apps.
Overlays are their own small world. product/, vendor/ and device/ trees often contain RRO
packages that change resources in a target without editing it. When a string or a colour does not
match the source, an overlay is the first thing to check.
build/ — how it is assembled#
build/soong/ is the Go implementation of the build system. build/make/ is the legacy Make build
and the Kati translation layer. build/release/ contains the release configurations that
trunk-stable builds select between.
The build is not incidental to reading the source. Android.bp files tell you what a module is,
what it depends on, and whether it is platform code, an app, or a vendor component.
The directories that surprise people#
A few paths are not where you expect, and knowing them saves a search.
libcore/ is not under frameworks/. It is its own top-level project. The Java core library
lives beside the platform rather than inside it because it is maintained as a separate body of code
with its own upstream relationship to OpenJDK.
external/ is a top-level directory full of other people's code. The JSON parser, the image
decoders, the compression libraries and the SQLite engine all live there. It is the largest
directory by project count and the one you should read last, because a bug in it is usually not an
Android bug.
test/ and tools/ are top-level. The platform's own test infrastructure and developer tools
are not inside a subsystem. test/vts/ is the vendor test suite; tools/ contains the scripts
that the build and CI use.
pdk/ and platform_testing/ exist in some checkouts and are easy to mistake for platform
code. They are packaging and test configuration, and a change there affects how the platform is
assembled or tested rather than what it does.
device/ and vendor/ — reference targets#
In AOSP, device/ contains reference configurations: the emulator, Cuttlefish, and Google's
reference devices. A real phone's device tree comes from the OEM, not from AOSP. vendor/ is
mostly empty in AOSP and is populated by the OEM's tree.
This is why "build AOSP for your phone" is not really a thing: your phone's device configuration is not in AOSP. You build AOSP for a reference target, or you build your OEM's tree.
How it evolved#
| API | Version | What changed |
|---|---|---|
| 1 | 1.0 |
|
| 17 | 4.2 Jelly Bean |
|
| 19 | 4.4 KitKat |
|
| 23 | 6.0 Marshmallow |
|
| 24 | 7.0 Nougat |
|
| 26 | 8.0 Oreo |
|
| 28 | 9 Pie |
|
| 29 | 10 |
|
| 30 | 11 |
|
The treble rows show why the map keeps changing: each modularity project moved a boundary, and a
moved boundary moves code. packages/modules/ is the newest major addition to the top-level map.
Under the hood#
- the android.* API surface that apps compile against
- the system services, mostly running inside system_server
- README.mdthe init language that starts the native layer
Curiosity corner#
- SystemUI is an app, not the framework. It lives in
packages/apps, is signed with the platform key, and can restart without rebooting the device. frameworks/baseis not one module. ItsAndroid.bpdefines many modules, including the framework library, the services library and the test suites.device/is reference only. Your phone's device tree is not in AOSP, which is why AOSP builds target emulators and reference devices.
Try it#
repo list | head -40
ls frameworks/base
ls packages/apps
ls system/coreExample output
Illustrative — requires a local AOSP checkout.Build it#
N01 — Build and boot AOSP walks through a checkout and a build, which is the practical version of this map.
Check yourself#
Three questions to answer without looking back. Open each one only after you have tried.
1. What does a Manager object in your app actually hold?
A Binder proxy to a service, not the service itself. The policy lives on the service side, usually
in system_server, and every call crosses a process boundary.
2. Why does the build use a declarative
Because a declarative module definition can be analysed. Soong can build a complete dependency
graph before running anything, which is what makes Ninja parallel and incremental. Conditionals in
a script would make the graph depend on execution.Android.bp instead of a script?
3. What is the difference between reading a facade and reading a service?
The facade defines the public contract — validation, defaults, deprecation. The service implements
the behaviour and holds the state. A bug in behaviour is almost always on the service side; a
compatibility question is almost always on the facade side.
Sources#
Sources
Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.
- docsModular system componentssource.android.comaccessed 2026-10-27↩
- sourcesystem/core/rootdir/init.rcandroid.googlesource.comaccessed 2026-10-27↩
- docsHardware abstraction layers (HALs)source.android.comaccessed 2026-10-27↩
- docsAndroid platform architecture (AOSP)source.android.comaccessed 2026-10-27↩
- docsBuild Androidsource.android.comaccessed 2026-10-27↩