For the complete documentation index, see llms.txt. This page is also available as Markdown.

Interview AOSP 2

1. Activity Internals

Activity Launch: From startActivity() to onResume()

1. Client Request The call enters ActivityTaskManagerService (ATMS) via Binder. In Android 10+, ActivityManagerService delegates task/stack management to ATMS.

// frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // Cross-process call into system_server
    int result = ActivityTaskManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent, ...);
}

2. ATMS Resolve & Intent Flags ActivityStarter (inside ATMS) resolves the intent via PackageManagerInternal, computes the launch mode (standard, singleTop, singleTask, singleInstance), and determines if a new task is needed.

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, ...) {
    // Compute launch flags
    computeLaunchingTaskFlags();
    // Find or create Task
    mTargetTask = mPreferredTaskDisplayArea.getOrCreateRootTask(...);
    // Place activity in task
    mTargetStack.startActivityLocked(mStartActivity, ...);
}

3. Process Start via Zygote If the target app is not running, ATMS calls ProcessList.startProcessLocked(), which builds the ProcessRecord and issues a start() to Zygote.

4. ActivityThread Attach The new process starts ActivityThread.main(), creates the main Looper, and attaches to ATMS. ATMS replies with bindApplication() containing ApplicationInfo, providers, and configuration.

5. Application & Activity Creation ATMS schedules bindApplication() back to the app. ActivityThread creates the LoadedApk, Instrumentation, Application, and then schedules Activity.onCreate() via H.BIND_APPLICATION and H.LAUNCH_ACTIVITY.

6. Window & Surface Creation Activity.attach() creates a PhoneWindow. handleResumeActivity() adds the decor view to WindowManager, which triggers ViewRootImpl.setView(). ViewRootImpl requests a Surface from WindowManagerService via relayoutWindow(), and WMS allocates a SurfaceControl from SurfaceFlinger.


2. Zygote Internals

The Fork Model & USAP (Unspecialized App Process)

Zygote Startup init starts Zygote via app_process. It loads the Android runtime, preloads classes/resources, and enters a select() loop on a Unix domain socket (/dev/socket/zygote).

Preloading ZygoteInit preloads ~4000 classes, drawables, and shared libraries. This memory is marked read-only and shared across all children via Copy-on-Write (COW).

USAP (Unspecialized App Process) — Android 10+ To reduce fork latency, Zygote maintains a pool of pre-forked, idle processes (USAP). When an app launch request arrives, Zygote specializes a USAP process instead of forking from the main Zygote.

Fork & Specialization Zygote.forkAndSpecialize() calls native nativeForkAndSpecialize(), which uses fork(). Post-fork, the child calls specializeAppProcess() to drop privileges, set SELinux context, and apply seccomp-bpf filters.


3. Broadcast Internals

Broadcast Resolution, Scheduling, and ANR

Registration Receivers are registered either statically in AndroidManifest.xml (parsed by PMS at boot) or dynamically via Context.registerReceiver(). Dynamic receivers are stored in AMS.mRegisteredReceivers keyed by IIntentReceiver Binder.

Broadcast Enqueue broadcastIntentLocked() resolves the broadcast to a list of receivers (both manifest and registered). It creates a BroadcastRecord and places it in a queue.

  • Ordered: Enqueued to mOrderedBroadcasts. Delivered sequentially.

  • Parallel: Enqueued to mParallelBroadcasts. Delivered concurrently to registered receivers.

Delivery & ANR processNextBroadcast() dequeues records. For each receiver, it calls deliverToRegisteredReceiverLocked(). If the target process is not running, it starts it. An ANR is posted via mHandler.postDelayed(mBroadcastTimeout, timeout) (default 10s for foreground, 60s for background). If the receiver does not finish in time, broadcastTimeoutLocked() triggers ANR.

Background Restrictions (Android 8+) Implicit broadcasts (without a specific target component) are dropped for manifest-registered receivers unless the app is in the foreground or on a whitelist. Explicit broadcasts and registered receivers are still allowed.


4. Service Internals

startService() vs bindService()

startService() Path The client calls Context.startService(). This goes to ActivityManagerService.startService(). AMS creates a ServiceRecord, places it in mServicesByName, and if the service is not running, starts the process. The service is then created via scheduleCreateService() and scheduleStartService().

bindService() Path bindService() adds a ConnectionRecord linking the client IServiceConnection to the ServiceRecord. If the service is not created, it goes through scheduleCreateService(). Then scheduleBindService() is sent, which calls Service.onBind() in the app. The resulting IBinder is returned to the client via publishService().

Service Lifecycle & Death ServiceRecord tracks startId for each startService() call. stopService() removes the start request. When all starts are removed and no bindings exist, AMS schedules scheduleStopService(). If the hosting process dies, AMS calls serviceDiedLocked() and restarts the service if START_STICKY.


5. Creating a System Service

A system service lives in system_server and is accessible to apps via Context.getSystemService().

Step 1: Define the AIDL Interface

Add to frameworks/base/Android.bp in srcs for the framework module.

Step 2: Implement the Service

Step 3: Register in SystemServer

Step 4: Add to Context and SystemServiceRegistry

Step 5: Create the Manager Wrapper

Step 6: SELinux & Permissions

Add the permission in frameworks/base/core/res/AndroidManifest.xml:

Add SELinux rules in system/sepolicy/private/service.te and service_contexts:


6. Creating a Vendor Service

Vendor services live in the vendor partition, run in vendor processes, and are accessed by framework or other vendor code. They use hwbinder (HIDL) or vndbinder (stable AIDL).

Option A: HIDL HAL (Legacy but still common)

1. Define HIDL Interface

2. Generate Boilerplate Run hidl-gen to generate Android.bp, IMyDevice.h, BpHwMyDevice, BnHwMyDevice.

3. Implement the HAL

4. Build & Register

Register in manifest.xml:

5. Access from Framework

Option B: Stable AIDL HAL (Modern, Android 11+)

1. Define Stable AIDL

2. Implement

Or in C++:

3. Build

4. Register with APEX or vndservicemanager

For a vendor native service exposed via vndbinder:

Add to vendor/etc/vintf/manifest.xml:

Option C: Vendor Native Service (vndservicemanager)

For vendor-specific services not defined in VINTF, use vndservicemanager directly.

SELinux for Vendor Services

Accessing Vendor Service from Framework

Framework code must use ServiceManager.getService("vendor.acme.my_service") with the proper SELinux context (system_server must have find permission on vendor_acme_service). However, Treble restrictions prevent direct framework access to arbitrary vendor services; use a HAL interface or a passthrough HIDL interface instead.

Last updated