안드로이드 단말기의 전원 버튼을 누르면 부트로더와 리눅스 커널이 가동된 후, 유저 공간(User Space)에서 가장 먼저 init 프로세스가 실행됩니다. 이 init 프로세스가 Zygote를 깨우고, Zygote가 마침내 안드로이드 자바 프레임워크의 모든 서비스를 총괄하는 거대한 프로세스인 SystemServer를 포크(Fork)하게 되죠.
우리가 스마트폰이나 임베디드 보드를 사용할 때 체감하는 앱 전환, 화면 터치 반응, 배터리 절전 모드 등은 모두 이 SystemServer 프로세스 내부에서 돌고 있는 핵심 프레임워크 서비스들 덕분입니다. AOSP 환경에서 시스템을 커스텀하거나 성능 최적화를 하려면, 이 서비스들이 구체적으로 frameworks/base 디렉터리 어디에 위치해 있고 어떤 순서로 메모리에 적재되는지 명확히 알고 있어야 합니다. 이번 포스팅에서는 안드로이드 OS를 지탱하는 3대 핵심 서비스의 역할과 함께, SystemServer.java 소스 코드 리딩을 통한 부팅 단계별 초기화 시퀀스를 자세히 파헤쳐 보겠습니다.

📌 핵심 요약 3줄
- SystemServer는 안드로이드 프레임워크 자바 서비스들의 생명 주기를 관장하는 마스터 프로세스로, 메인 스레드의 부팅 시퀀스에 따라 순차 가동됩니다.
- OS 가동에 절대적으로 필요한 코어 기능들은 의존성에 따라 Bootstrap(필수), Core(코어), Other(기타) 서비스 단계로 쪼개어져 초기화됩니다.
- frameworks/base 디렉터리는 이러한 시스템 서비스 소스 코드(services/)와 앱 개발자용 공용 API 인터페이스(core/)가 분리된 구조를 가집니다.
1. 3대 핵심 프레임워크 서비스 기능 비교
안드로이드 시스템 내에서 가장 중추적인 역할을 수행하는 3대 서비스(AMS, PMS, WMS)의 담당 업무와 AOSP 내 실제 소스 코드 경로를 정리한 매핑 구조입니다.
| 서비스 명칭 (약어) | AOSP 소스 코드 디렉터리 경로 | 핵심 담당 시스템 역할 | 부팅 초기화 단계 |
| ActivityManagerService (AMS) |
frameworks/base/services/core/java/ com/android/server/am/ |
애플리케이션 프로세스 포크 및 포그라운드/백그라운드 태스크 제어, 앱 생명 주기(Lifecycle) 및 브로드캐스트 리시버 중계 | Bootstrap Services (가장 먼저 가동) |
| PowerManagerService (PMS) |
frameworks/base/services/core/java/ com/android/server/power/ |
커널 레벨의 WakeLock 상태 관리, 단말기 디스플레이 백라이트 및 밝기 제어, 배터리 절전 상태 변화 감지 | Bootstrap Services (가장 먼저 가동) |
| WindowManagerService (WMS) |
frameworks/base/services/core/java/ com/android/server/wm/ |
화면 위에 그려지는 모든 윈도우 창의 레이아웃 영역 계산, Z-Order(적재 순서) 관리, 터치 및 키 입력 이벤트 분배 | Other Services (의존성 해결 후 가동) |
2. frameworks/base/ 디렉터리 구조 이해
AOSP 환경에서 프레임워크 서비스나 새로운 API를 추가하려면 frameworks/base/ 내부의 패키지 분리 규칙을 이해해야 컴파일 의존성이 꼬이지 않습니다.
frameworks/base/
├── core/ # 앱 개발자가 참조하는 Android SDK 표준 API 및 코어 런타임 라이브러리
├── graphics/ # 캔버스, 폰트, 이미지 디코딩 등 2D/3D 그래픽 프레임워크 소스
├── media/ # 오디오, 비디오 재생 및 레코딩 관리를 위한 자바 스택
├── telephony/ # 기지국 연동, SMS, LTE/5G 데이터 통신 관련 무선 모듈 프레임워크
└── services/ # SystemServer 프로세스가 메모리에 직접 올려 구동하는 순수 시스템 소스
└── core/java/com/android/server/
├── am/ # ActivityManagerService 및 프로세스 스케줄러 소스
├── power/ # PowerManagerService 및 배터리 세이버 소스
└── wm/ # WindowManagerService 및 디스플레이 윈도우 제어 소스
3. SystemServer 초기화 시퀀스 분석
안드로이드의 모든 자바 프레임워크 서비스는 SystemServer.java 파일의 main() 메서드에서 시작하여 거대한 단일 프로세스로 바인딩됩니다.
3.1 진입점 및 실행 흐름 (SystemServer.java)
// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
// Zygote에 의해 프로세스가 생성되면 최우선으로 실행됩니다.
new SystemServer().run();
}
private void run() {
try {
// 서비스 오버헤드와 상호 의존성을 고려하여 3단계로 엄격하게 분리하여 초기화합니다.
startBootstrapServices(); // 1단계: 필수 부트스트랩 서비스
startCoreServices(); // 2단계: 핵심 코어 서비스
startOtherServices(); // 3단계: 나머지 부가/주변장치 서비스
} catch (Throwable ex) {
Slog.e("System", "SystemServer 실행 중 치명적 예외 발생!", ex);
throw ex;
}
}
3.2 필수 서비스 적재: startBootstrapServices()
이 단계에서는 다른 서비스들이 정상 동작하기 위해 '무조건' 먼저 켜져 있어야 하는 극초기 필수 서비스들을 구동합니다. 디바이스의 전원 상태를 다루는 PMS와 프로세스 생성을 관장하는 AMS가 여기에 속합니다.
private void startBootstrapServices() {
// 전원 관리 서비스 가동 (커널 WakeLock 연동을 위해 극초기 구동 필요)
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 액티비티 매니저 서비스 가동 (앱 프로세스 관리를 위한 아키텍처 베이스)
mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager);
}
3.3 주변장치 및 UI 구동: startOtherServices()
부트스트랩과 코어 서비스들이 안정적으로 메모리에 정착하면, 디스플레이 렌더링을 제어하는 WMS를 비롯하여 센서, 블루투스, 네트워크 등 하드웨어 의존성이 짙은 나머지 서비스들을 차례로 깨웁니다.
private void startOtherServices() {
// 디스플레이 및 입력 장치 제어를 위한 WindowManagerService 빌드
mWindowManagerService = WindowManagerService.main(context, inputManager,
!mFactoryTestMode, mInitSafeMode, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, mWindowManagerService,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
}
🛠️ 개발을 위한 팁 (Tips)
- 내 커스텀 서비스의 초기화 단계 선정 규칙: AOSP에 나만의 프레임워크 서비스를 추가할 때, 무조건 startBootstrapServices()에 코드를 넣으면 안 됩니다. 이 단계는 하부 파일 시스템 유닛이나 네트워크 뼈대가 전혀 구성되지 않은 완전 날것의 상태입니다. 내가 만드는 서비스가 파일 입출력을 하거나 다른 시스템 서비스의 API를 참조해야 한다면 반드시 startOtherServices() 단계의 하단부, 혹은 시스템 부팅 완료 브로드캐스트(PHASE_BOOT_COMPLETED) 시점에 태스크를 수행하도록 이벤트를 리스닝하는 설계가 훨씬 안전합니다.
- SystemServer 디버깅을 위한 Slog 활용: 프레임워크 서비스를 수정할 때는 일반 앱에서 쓰는 Log.d 대신 android.util.Slog 클래스를 사용해 로그를 남겨야 합니다. Slog로 남긴 메시지는 시스템 서버 전용 데몬 로그 버퍼로 유입되므로, 터미널창에 adb logcat -b system 명령어를 주어 프레임워크 초기화 시점에 뿜어져 나오는 핵심 에러와 경고 메시지만 깨끗하게 필터링하여 추적할 수 있습니다.
⚠️ 흔히 하는 실수 (Common Mistakes)
- 초기화 메서드 내 내부 루프 유발로 인한 부팅 무한 루프(Bootloop): SystemServer 내부의 startBootstrapServices()나 startOtherServices() 메서드는 하나의 메인 스레드 위에서 동기(Synchronous) 방식으로 나열된 서비스들을 하나씩 순차적으로 인스턴스화합니다. 내가 만든 서비스 내부 초기화 코드에 루프나 소켓 연결 대기 같은 블로킹 코드가 숨어있으면 다음 순서에 있는 WMS나 센서 서비스가 영원히 켜지지 못합니다. 결국 시스템 와치독(Watchdog)이 가동되어 보드가 무한 재부팅되는 참사가 벌어지므로 무거운 네트워크/IO 연산은 반드시 별도 워커 스레드로 분리해 주어야 합니다.
- frameworks/base/core와 services 간의 패키지 참조 혼선: 간혹 컴파일 편의를 위해 frameworks/base/core 레이어에 존재하는 공용 API 클래스 내부에서 services/core 밑에 있는 순수 시스템 클래스 객체를 직접 임포트(Import)하여 참조하려는 실수를 하곤 합니다. 안드로이드 빌드 아키텍처상 core 라이브러리가 먼저 빌드된 후 services가 빌드되기 때문에 역방향 참조는 무조건 컴파일 타임에 Symbol Not Found 에러를 냅니다. 두 레이어 간 데이터 교환이 필요하다면 반드시 AIDL 인터페이스라는 통일된 다리를 설계하여 넘어가야 합니다.
5. 결론
AOSP 개발의 첫걸음은 SystemServer.java가 그리는 거대한 밑그림을 온전히 내 것으로 만드는 일입니다. AMS, PMS, WMS 같은 핵심 프레임워크 서비스들은 각자 독립적으로 노는 것처럼 보이지만, 부팅 시퀀스라는 정교한 톱니바퀴 속에서 철저한 순서 룰을 지키며 가동되고 있습니다.
이 계층적 의존 관계와 frameworks/base 내부의 디렉터리 분리 규칙을 명확히 파악하고 나면, OS 업그레이드나 벤더 포팅 작업을 할 때 아키텍처가 꼬여 발생하는 수많은 데드락과 컴파일 예외를 슬기롭게 대처할 수 있게 됩니다. 시스템 서비스 구동 과정에서 특정 단계에 코드가 걸려 부팅이 넘어가지 않거나 로그캣에 알 수 없는 자바 바인더 에러가 찍힌다면 언제든 댓글로 소스를 공유해 주세요. 함께 머리를 맞대고 디버깅해 봅시다!
'Android System & AOSP Engineering > AOSP Framework & Custom Services' 카테고리의 다른 글
| Android AOSP 가이드: AIDL 생성부터 Context.getSystemService() 등록까지 전 과정 (0) | 2025.05.26 |
|---|---|
| AOSP 커스텀 서비스 개발: 사용자 정의 Framework Service 설계부터 Android.bp 빌드까지 (0) | 2025.05.24 |
| Android Framework Service 구현 가이드: AIDL부터 Binder IPC 등록까지 (0) | 2025.05.22 |
| Android AOSP 아키텍처 이해: Framework Service vs System Service 차이점 (0) | 2025.05.20 |
| Android 시스템 최적화 가이드: 프로파일링, 전원 관리, 부팅 속도 개선 기법 (0) | 2025.04.23 |