안드로이드는 전 세계 수만 가지 종류의 스마트폰, 태블릿, 키오스크, 자동차 인포테인먼트(IVI) 등 다양한 하드웨어에서 동작하는 범용 운영체제입니다. 그런데 문득 신기하지 않으신가요? 삼성, 구글, 샤오미 등 제조사마다 사용하는 카메라 센서, 오디오 칩셋, AP(Application Processor)가 전부 제각각인데, 우리가 구글 플레이스토어에서 다운로드한 앱들은 기기를 가리지 않고 모두 똑같이 카메라를 켜고 소리를 재생합니다.
이것이 가능한 이유는 하드웨어의 복잡한 세부 사양을 뒤로 감추고 상위 소프트웨어 레이어에 표준화된 통로를 제공하는 HAL(Hardware Abstraction Layer, 하드웨어 추상화 계층)이 존재하기 때문입니다. 이번 포스팅에서는 안드로이드 플랫폼 개발의 핵심이자 진입 장벽인 HAL의 개념과 계층 구조를 알아보고, AOSP 소스 코드를 통해 실제 구동 메커니즘을 파헤쳐 보겠습니다.

📌 핵심 요약 3줄
- **HAL(하드웨어 추상화 계층)**은 상위 안드로이드 프레임워크가 하드웨어의 세부 제어 방식을 몰라도 공통 API를 통해 부품을 제어할 수 있도록 돕는 표준 인터페이스입니다.
- 안드로이드는 Project Treble을 기점으로 OS 영역(/system)과 벤더 영역(/vendor)을 엄격히 분리했으며, 최신 안드로이드 시스템은 AIDL 기반의 하드웨어 인터페이스를 표준으로 사용합니다.
- HAL을 통해 제조사(Vendor)는 구글의 순정 소스코드를 수정하지 않고도 자사 칩셋에 최적화된 고유 기능을 독립적으로 구현하고 OS 업데이트를 신속하게 진행할 수 있습니다.
1. HAL이 필요한 이유와 핵심 역할
만약 HAL이 없다면 어떻게 될까요? 새로운 카메라 센서가 출시될 때마다 안드로이드 프레임워크 소스코드를 통째로 뜯어고쳐야 하는 대재앙이 발생할 것입니다. HAL은 이러한 문제를 아래의 4가지 핵심 가치로 해결합니다.
| 핵심 역할 | 세부 메커니즘 및 가치 | 실제 적용 예시 |
| 하드웨어 독립성 제공 | 상위 프레임워크와 하드웨어를 디커플링하여 동일한 OS 코드가 다른 하드웨어에서도 일관되게 동작하도록 보장합니다. | 미디어 서버 코드는 그대로 둔 채 오디오 코덱 칩셋만 교체 가능 |
| 벤더 구현의 유연성 | 구글이 정한 표준 API 스펙만 준수하면, 제조사는 내부 비공개 소스코드를 활용해 성능 최적화를 자유롭게 수행할 수 있습니다. | 퀄컴/미디어텍 ISP 칩셋 특성에 맞춘 카메라 파이프라인 독자 튜닝 |
| 보안 및 라이선스 보호 | 리눅스 커널 드라이버는 GPL 라이선스를 따르므로 소스코드를 공개해야 하지만, 유저 영역(User Space)에 존재하는 HAL은 소스코드를 독점(Closed Source) 형태로 보호할 수 있습니다. | 제조사의 핵심 알고리즘이 담긴 오디오 DSP, 생체인식(지문/Face ID) 드라이버 보호 |
| 프레임워크 개발 단순화 | 앱 개발자나 플랫폼 개발자는 센서의 레지스터 제어 방식 같은 로우 레벨 지식 없이 가이드된 자바/코틀린 API만 호출하면 됩니다. | SensorManager를 통해 가속도 센서 값을 한 줄로 읽어오기 |
2. 안드로이드 아키텍처 스택과 HAL의 위치
안드로이드 소프트웨어 스택을 위에서 아래로 내려다보면 HAL이 어디에 징검다리를 놓았는지 명확히 보입니다.
| 계층 (Layer) | 주요 언어 | 담당 역할 | 서술 및 연결 방식 |
| 1. Application & Framework | Java / Kotlin | 사용자 앱 및 OS 핵심 서비스 공급 | 상위 Level 시스템 서비스 가동 (AudioService 등) |
| 2. JNI (Java Native Interface) | C++ / Java | 자바 레이어와 네이티브 레이어의 소통 가교 | 자바의 호출을 C++ 함수 포인터로 매핑 및 변환 |
| 3. AIDL / HIDL (HAL Interface) | AIDL / C++ | [현 위치] 프레임워크와 HAL 프로세스 간의 IPC 통신 통로 | 바인더(Binder) 통신을 통해 유저 스페이스 바운더리 제어 |
| 4. Vendor HAL Implementation | C / C++ | 제조사가 칩셋 사양에 맞게 실제 하드웨어 로직을 코딩한 영역 | /vendor/bin/hw/ 경로에 독립된 프로세스로 상주 |
| 5. Linux Kernel Driver | C | 하드웨어 레지스터에 물리적 신호를 인가하는 최하위 드라이버 | ioctl, read, write 시스템 콜을 통한 하드웨어 제어 |
3. AOSP 소스 코드로 보는 HAL 인터페이스와 구현
실제 소스 코드를 보면 HAL이 어떻게 선언되고 구현되는지 더 직관적으로 이해할 수 있습니다. 안드로이드에서 가장 대중적인 오디오(Audio) 인프라를 기준으로 살펴보겠습니다.
3.1 인터페이스 정의 (AIDL 예시)
최신 안드로이드 시스템은 인터페이스 정의 언어인 AIDL을 사용하여 HAL 규격을 선언합니다. 구글이 기틀을 잡아놓은 인터페이스 구조는 아래와 흡사합니다.
// hardware/interfaces/audio/aidl/android/hardware/audio/core/IModule.aidl
package android.hardware.audio.core;
interface IModule {
// 오디오 하드웨어의 마스터 볼륨을 설정하는 표준 인터페이스 선언
void setMasterVolume(float volume);
// 현재 기기에 연결된 마이크 장치 리스트를 배열로 반환
MicrophoneInfo[] getMicrophones();
}
3.2 벤더(제조사)의 실제 C++ 구현부
제조사는 위 AIDL 인터페이스를 상속받아 자사 사운드 칩셋 매뉴얼에 맞는 물리적인 제어 코드를 작성합니다.
// hardware/interfaces/audio/aidl/default/Module.cpp (예시 번역 코드)
#include <android/hardware/audio/core/BnModule.h>
class MyAudioModule : public BnModule {
ndk::ScopedAStatus setMasterVolume(float volume) override {
// 벤더가 하드웨어 오디오 코덱 레지스터 값을 직접 변경하거나
// 커널 믹서 드라이버(ALSA 소켓 등)에 하드웨어 볼륨 제어 명령을 전달하는 구간
this->master_volume = volume;
// 하드웨어 제어가 성공했음을 프레임워크에 알림
return ndk::ScopedAStatus::ok();
}
private:
float master_volume;
};
이렇게 분리된 구조 덕분에 구글 프레임워크 개발자는 IModule::setMasterVolume()만 호출하면 되고, 실제 볼륨이 커지는 세부 원리는 하단의 MyAudioModule이 책임지게 됩니다.
4. Project Treble과 /vendor 파티션의 격리
안드로이드 8.0 이전에는 HAL 라이브러리가 프레임워크 프로세스 내부로 직접 동적 로딩(dlopen)되는 구조였습니다. 이 때문에 OS를 한 단계 업데이트하려면 HAL 코드까지 한꺼번에 다시 빌드하고 테스트해야 해서 파편화와 업데이트 지연이 심각했습니다.
구글은 이를 해결하기 위해 Project Treble을 도입했습니다. 프레임워크가 있는 /system 파티션과 제조사 HAL 코드가 있는 /vendor 파티션을 물리적으로 분리한 것입니다. 둘 사이는 독립된 프로세스로서 바인더(Binder) IPC를 통해서만 데이터를 주고받습니다. 결과적으로 제조사는 시스템 파티션이 통째로 리프레시(OS 판올림)되어도 벤더 파티션에 있는 기존 HAL 고유 코드를 그대로 재사용할 수 있게 되었습니다.
💡 안드로이드 HAL 개발을 위한 실전 팁
- VINTF 매니페스트(manifest.xml) 등록 필수 파악: 내가 만든 커스텀 HAL 서비스를 벤더 파티션에 멋지게 띄웠더라도 상위 프레임워크가 이를 인지하지 못해 통신 에러가 나는 경우가 다반사입니다. 안드로이드 시스템은 가동될 때 VINTF(Vendor Interface Object) 검증을 수행하므로, /vendor/etc/vintf/manifest.xml 파일에 내가 추가한 AIDL HAL 서비스명과 인터페이스 버전 정보가 정확히 기재되어 있는지 반드시 대조해야 합니다.
- dumpsys 명령어로 HAL 상태 실시간 모니터링하기: 내가 만든 HAL 서비스가 정상적으로 바인더에 등록되어 살아있는지, 프레임워크와 연결은 잘 되었는지 확인하고 싶다면 터미널에 adb shell dumpsys android.hardware.audio.core.IModule/default (오디오 예시) 처럼 서비스 경로를 명시해 보세요. 현재 HAL 인스턴스의 내부 디버깅 상태를 손쉽게 추적할 수 있어 로그캣(logcat)만 붙잡고 있을 때보다 트러블슈팅 시간이 훨씬 단축됩니다.
⚠️ 흔히 하는 실수
- SELinux 거부(Avc Denied)로 인한 서비스 차단: 커스텀 HAL을 만들 때 가장 많이 하는 실수가 바로 SELinux 보안 정책을 빠뜨리는 것입니다. 안드로이드는 매우 엄격한 SELinux 통제를 따르기 때문에, 새로 만든 HAL 실행 파일에 적절한 도메인 권한(system_server가 vendor_hal_xxx_exec를 실행할 수 있도록 허용)을 주지 않으면, 루트 권한으로 빌드했더라도 avc: denied 에러를 뿜으며 바인더 통신 단계에서 가차 없이 차단당합니다. device/custom/sepolicy/ 하위에 명확한 .te 규칙을 세팅해 주는 습관을 들여야 합니다.
- HAL 내부에서 블로킹(Blocking) 함수 무한 대기: HAL 서비스는 시스템 전반의 하드웨어를 공유하는 공용 서번트 프로세스입니다. 만약 벤더 HAL 내부에서 하드웨어 칩셋의 응답을 기다린답시고 루프를 돌며 스레드를 무한정 블로킹(Deadlock 혹은 Long Sleep) 시켜버리면, 상위 프레임워크의 시스템 서비스 전체가 먹통이 되며 결국 안드로이드 시스템의 감시 기동대인 워치독(Watchdog)이 작동해 단말기가 스스로 재부팅되는 현상이 발생하므로 하드웨어 인터럽트나 비동기 콜백 구조를 지향해야 합니다.
5. 결론
하드웨어 추상화 계층(HAL)은 안드로이드 생태계의 파편화를 막고, 구글의 소프트웨어 확장성과 제조사의 하드웨어 독립성을 동시에 만족시키는 아키텍처 공학의 결정체입니다. 레거시 audio_hw.c 형태의 구조에서 시작해 Treble 아키텍처를 거쳐 현재의 AIDL 통신 기반 프로세스로 진화하기까지, HAL의 변화 메커니즘을 파악하는 것은 플랫폼 엔지니어의 핵심 역량입니다.
이제 빌드 시스템과 환경 세팅, 그리고 하드웨어를 제어하는 HAL의 기본 개념까지 모두 정복하셨습니다!
'Android System & AOSP Engineering > AOSP Framework & Custom Services' 카테고리의 다른 글
| 안드로이드 HAL과 리눅스 커널 드라이버의 연결 고리: 시스템 콜 기반 하드웨어 제어 분석 (0) | 2025.03.21 |
|---|---|
| 안드로이드 HAL의 진화: 레거시 구조부터 HIDL을 거쳐 AIDL HAL까지 완벽 분석 (0) | 2025.03.20 |
| AOSP 커스텀 안드로이드 빌드 환경 구축 가이드: 환경 설정부터 에뮬레이터 구동까지 (0) | 2025.03.18 |
| AOSP 안드로이드 빌드 시스템 총정리: Android.mk(Make)에서 Android.bp(Soong)로의 진화 (0) | 2025.03.17 |
| 안드로이드(Android) 부팅 과정 총정리: 전원 버튼 클릭부터 홈 화면까지 (AOSP 소스 코드 포함) (0) | 2025.03.16 |