이 가이드에서는 SDV 플랫폼에서 실행되는 서비스와 애플리케이션을 디버깅하는 데 필요한 필수 도구와 기법을 간략하게 설명합니다.
기기에 연결
기기에 연결하고 기기와 상호작용하는 기본 도구는 Android 디버그 브리지 (adb)입니다. adb가 시스템 경로에 있는지 확인합니다.
네트워크를 사용하여 연결
기기가 동일한 네트워크에 있고 IP 주소를 알고 있다면 이더넷으로 연결할 수 있습니다. 시스템은 adb에 네트워크 연결만 사용합니다.
# Connect to the device using its IP address and default port
adb connect <device_ip_address>:5555
여러 기기에 연결하기
단일 워크스테이션에서 여러 기기를 관리하려면 서로 다른 IP 주소를 통해 기기에 연결하면 됩니다. 단일 호스트에서 여러 VM을 실행하는 경우 각 기기에 서로 다른 포트를 할당해야 합니다. 이렇게 하려면 각 SDV 기기의 adb 데몬이 고유한 포트(예: 첫 번째 기기의 경우 5555, 두 번째 기기의 경우 5556)에서 수신 대기하도록 구성해야 합니다. 호스트가 이러한 포트를 다른 게스트로 전달하도록 구성할 수도 있습니다.
# Connect to the first device
adb connect <device_1_ip_address>:5555
# Connect to a second device
adb connect <device_2_ip_address>:5555
# Connect to a second VM on first device on different port
adb connect <device_1_ip_address>:5556
# List all connected devices to verify
adb devices
후속 adb 명령어를 실행할 때 전체 주소 (ip:port)와 함께 -s 플래그를 사용하여 특정 기기를 타겟팅할 수 있습니다.
# Run a shell command on the second VM on first device in the above example
adb -s <device_1_ip_address>:5556 shell
로그 보기
서비스가 실패하거나 예기치 않게 작동하는 경우 먼저 로그를 확인합니다.
logcat (Android 로그) 사용
logcat는 시스템 서비스, 에이전트, 서비스 번들의 로그를 표시합니다.
# View all logs in real-time
adb logcat
# Filter logs by a specific tag (e.g., the name of your service)
adb logcat -s MyServiceTag
# Filter logs by priority (V: Verbose, D: Debug, I: Info, W: Warn, E: Error, F: Fatal)
# This shows only Error and Fatal messages for a specific tag
adb logcat MyServiceTag:E *:S
# Clear old logs before viewing new ones
adb logcat -c && adb logcat
# Show all logs and return
adb logcat -d
# Color logs by level
adb logcat -v color
# Show timestamps as time since boot
adb logcat -v monotonic
dmesg (커널 로그) 사용
dmesg는 Linux 커널의 로그를 표시합니다. 이는 다음을 디버깅하는 데 매우 중요합니다.
- 하드웨어 및 드라이버 문제
- 커널 패닉
- SELinux 거부 (
avc: denied) - logcat에도 표시됨
# View all kernel messages
adb shell dmesg
# Follow kernel messages in real-time
adb shell dmesg -w
Cuttlefish에서 로그 액세스
Cuttlefish 가상 기기에서 실행하는 경우 호스트 머신의 파일 시스템에서 로그 파일에 직접 액세스할 수 있습니다. 이는 adb를 사용할 수 없는 경우에 특히 유용합니다. Cuttlefish를 시작하면 모든 디버깅 경로가 출력되며 실행 중인 모든 인스턴스에 대해 cvd fleet를 사용하여 디버깅 경로를 조회할 수도 있습니다.
- Logcat (Android 로그):
cuttlefish/instances/cvd-1/logs/logcat - 커널 로그:
cuttlefish/instances/cvd-1/logs/kernel.log - Cuttlefish 런처 로그:
cuttlefish/instances/cvd-1/logs/launcher.log(Cuttlefish 환경 자체를 디버깅하는 데 유용함)
cat, less, tail -f과 같은 표준 명령줄 도구를 사용하여 이러한 파일을 실시간으로 볼 수 있습니다.
셸 및 파일 시스템과 상호작용
셸 액세스 권한을 얻어 기기에서 직접 명령어를 실행하고 프로세스 상태를 확인하며 파일 시스템을 탐색합니다.
# Open an interactive shell on the device
adb shell
# From within the shell, you can check running processes
ps -A
# Or check the status of a specific service managed by init
getprop init.svc.<service_name>
파일 시스템 작업 수행
adb push 및 adb pull를 사용하여 호스트 머신과 기기 간에 파일을 이동합니다. 이를 사용하여 테스트 스크립트를 배포하거나 구성을 업데이트하거나 크래시 덤프를 검색합니다.
# Push a file from your computer to the device
adb push my_local_file.txt /data/local/tmp/
# Pull a file from the device to your computer
adb pull /data/tombstones/tombstone_00 .
애플리케이션 디버그 (C++/Rust)
온라인 또는 오프라인으로 애플리케이션을 디버그할 수 있습니다.
실시간 디버깅에 lldb 사용
다음 단계에 따라 lldb를 사용하여 실시간으로 서비스를 디버그합니다 (Android Studio for Platform에서 디버거를 연결하려면 디버그 및 테스트 및 플랫폼 코드 디버그 참고).
루트 권한으로
adb를 다시 시작합니다 (포트 전달에 필요).adb root바이너리에 디버깅 기호가 있는 경우
out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE]에서 제거되지 않은 버전을 푸시합니다. 예를 들어system_ext및sdv_core_cf에서rpcagent를 업로드하려면 다음을 실행합니다.adb push out/target/product/sdv_core_cf/symbols/system_ext/bin/rpcagent /data/local/tmplldbclient.py편의 스크립트를 사용하여 LLDB 클라이언트에 연결합니다.# Run and connect a binary on device, run on host: lldbclient.py -r /data/local/tmp/rpcagent # Connect to an existing process with PID 2759 lldbclient.py -p 2759이 스크립트는
lldb를 원격으로 연결합니다. 사용 가능한 모든 플래그를 보려면lldbclient.py --help를 실행합니다.
크래시 덤프 (tombstone) 분석
서비스가 비정상 종료되면 tombstone 파일이 /data/tombstones/에 생성됩니다.
파일에는 스택 트레이스, 메모리 맵, 기타 중요한 정보가 포함됩니다.
tombstone 파일을 가져온 다음 기호 인식 도구 (예: lldb 또는 전용 스크립트)를 사용하여 바이너리의 제거되지 않은 버전으로 분석합니다.
성능 분석
SDV는 성능 측정을 위한 여러 도구를 지원합니다.
CPU 및 메모리 사용량 확인
top: CPU 사용량별로 정렬된 실행 중인 프로세스를 실시간으로 보여줍니다.adb shell top -m 10 # Show top 10 processesprocrank: 특정 프로세스 또는 전체 시스템의 메모리 사용량에 관한 세부 분석을 제공합니다.adb shell procrank
서비스 상태에 dumpsys 사용
dumpsys는 Android 시스템 서비스의 내부 상태를 쿼리하는 강력한 도구입니다.
# List all available services
adb shell dumpsys -l
# Dump the state of a specific service or agent
adb shell dumpsys <service_name>
성능 분석에 torq 사용
torq는 Android에서 프로파일링 및 추적 작업을 간소화하는 명령줄 도구입니다. 시스템 성능 분석 중에 Simpleperf, Perfetto 및 기타 일반적인 작업을 실행할 수 있습니다.
추적에 Perfetto 사용
Perfetto는 Android에서 시스템 전체 추적을 위한 표준 도구입니다. Perfetto를 사용하면 시스템 이벤트, 앱 수준 트레이스 포인트, 성능 카운터를 기록하고 타임라인에 시각화할 수 있습니다.
주요 단계:
- C++ 또는 Rust 코드에 trace 포인트를 추가합니다.
- C++:
TRACE_EVENT매크로와 함께 Perfetto SDK를 사용합니다. - Rust: Perfetto와 호환되는 ATrace 이벤트를 내보내는
tracing크레이트를 사용합니다.
- C++:
- textproto 구성 파일을 만들어 데이터 소스 (예:
ftrace,track_event), 카테고리, 태그를 지정합니다. - 구성 파일과 함께
record_android_trace스크립트(external/perfetto/tools/record_android_trace)를 사용하여 기기에서 트레이스를 캡처합니다. - Perfetto 웹 UI에서 생성된 트레이스 파일을 열어 시스템 동작을 분석하고 병목 현상을 식별하며 서비스 상호작용을 파악합니다.
계측, 구성, 수집에 관한 자세한 안내는 추적을 사용하여 시스템 성능에 대한 통계 얻기를 참조하세요.
프로파일링에 Simpleperf 사용
Simpleperf는 Linux perf와 유사한 Android 성능 프로파일링을 위한 다목적 명령줄 도구입니다.
일반적인 사용 사례:
- CPU 프로파일링: CPU 시간을 가장 많이 소비하는 함수를 식별합니다.
- 오프 CPU 분석: 스레드가 절전 모드이거나 차단된 이유를 분석합니다.
- 하드웨어 카운터: 하드웨어 성능 카운터에 액세스합니다.
명령어 예시:
# Go to simpleperf scripts
cd system/extras/simpleperf/scripts
# Profile system for 20 seconds and record call graph
./app_profiler.py --system_wide -r "--call-graph fp --duration 20"
# Record a profile for a specific process (PID 1)
./app_profiler.py --pid 1 -r "--call-graph fp --duration 5"
# Pull the profile data
adb pull /data/local/tmp/perf.data .
# Generate a report with symbol resolution
./report_html.py --add_source_code --source_dirs $ANDROID_BUILD_TOP --add_disassembly -o report.html
Simpleperf는 더 많은 이벤트와 옵션을 제공합니다. 포괄적인 문서는 Simpleperf 가이드를 참고하세요.
SELinux 거부
증상: 서비스가 시작되지 않거나, 파일에 액세스하지 못하거나, 기능을 사용하지 못하고 dmesg 또는 logcat에 avc: denied 메시지가 표시됩니다.
[ 123.456] avc: denied { read } for pid=789 comm="my_service" name="some_file" dev="sda1" ino=123 scontext=u:r:my_service_t:s0 tcontext=u:object_r:some_file_t:s0 tclass=file permissive=0
빠른 디버그 (개발 전용)
SELinux 시행을 일시적으로 사용 중지하여 문제가 해결되는지 확인할 수 있습니다. 이렇게 하면 SELinux 정책 규칙이 누락되어 문제가 발생했음을 확인할 수 있습니다.
# Disabling SELinux requires root permission
adb root
# Set SELinux to permissive mode
adb shell setenforce 0
# Check the current mode (should return "Permissive")
adb shell getenforce
수정: 거부 메시지에 관한 Android 소스 트리의 audit2allow 도구입니다. 이렇게 하면 기기의 SELinux 구성에 추가할 올바른 .te 정책 규칙이 생성됩니다.