안드로이드 공부:: 1단원 ~ 3.3 단원
-
안드로이드 프레임워크 개요
- 안드로이드는 모바일 디바이스용 애플리케이션을 쉽게 제작하기 위한 소프트웨어 프레임워크를 제공. (안드로이드 SDK)
- 안드로이드 애플리케이션 개발자는 제공되는 프레임워크로 얼마든지 애플리케이션을 개발할 수 있기에 프레임워크를 제대로 이해하지 않아도 됨. but 안드로이드 플랫폼 개발자라면 프레임워크에 대한 심도 있는 이해 필수.
1.1 안드로이드의 소스코드 구조
kernal: 안드로이드의 리눅스 커널 2.6 frameworks: 안드로이드 프레임워크 packages: 안드로이드 기본 애플리케이션, 컨텐트 프로바이더 등 system: 안드로이드 init 프로세스, 블루투스 도구 모음 등 bionic: 안드로이드 표준 C 라이브러리 bootloader: 참고용 안드로이드 부트로더 build: 안드로이드 빌드 시스템 cts: 안드로이드 호환성 테스트 관련 소스 dalvik: 달빅 가상 머신 external: 안드로이드에서 사용하는 오픈소스들 hardware: 안드로이드 HAL(Hardware Abstraction Layer) 소스
1.2 부팅 프로세스로 알아보는 안드로이드 프레임워크
- 복잡하면서도 거대한 안드로이드 프레임워크를 분석하기 위해 안드로이드 플랫폼의 시작점인 부팅 과정 주목. - 부팅 과정 1) 리눅스 커널: 부팅시 부트로더를 통해 시작되어, 커널 초기화를 수행 후 마지막 과정에서 init 프로세스 호출. 2) init: 각종 디바이스 초기화. 안드로이드 프레임워크 동작에 필요한 각종 데몬(USB 데몬, 안드로이드 디버그 브리지 데몬, 디버거 데몬, 무선 인터페이스 레이어 데몬), 컨텍스트 매니저, 미디어 서버 등 실행. 3) 컨텍스트 매니저 - 안드로이드의 시스템 서비스 관리. 시스템 서비스 안드로이드 프레임워크를 구성하는 중요 컴포넌트로서 각종 애플리케이션 제작에 필요한 중요 API를 제공하는 역할을 수행함. - 안드로이드 내에서 동작하는 각종 시스템 서비스에 대한 정보는 컨텍스트 매니저에게서 얻어짐. - 시스템 서비스를 이용하고자 하는 애플리케이션이나 프레임워크의 내부 모듈은 이를 서비스 매니저에게 요청해야하고, 요청 후 바인더라는 안드로이드의 자체적인 IPC(Inter process communication) 메커니즐을 통해 시스템 서비스를 이용할 수 있음. - 이를 위해서 안드로이드의 모든 시스템 서비스는 부팅 시 자신의 핸들 정보를 컨텍스트 매니저에 등록해야함. 또한 이러한 등록 과정에서도 프로세스 간 통신 수행을 위해 바인더 IPC가 이용됨. 4) 미디어 서버: 오디오 출력 담당이나 카메라 서비스와 같이 C/C++ 기반으로 작성되어 있는 네이티브 시스템 서비스를 실행. 5) Zygote: 안드로이드 애플리케이션의 로딩 시간을 단축하기 위한 프로세스. 모든 자바 기반 안드로이드 애플리케이션을 이를 통해 fork 된 프로세스 상에서 동작. 6) 시스템 서버 - Zygote에서 최초로 fork되어 실행되는 안드로이드 애플리케이션 프로세스. 자바 시스템 서비스(이 역시 컨텍스트 매니저에 등록되어야 함) 실행 역할. - 바인더 IPC 통하여 자바 시스템 서비스를 C언어 기반의 서비스 매니저에 등록하려면 자바와 C언어 간의 인터페이스 역할을 하는 JNI(Jave Native Interface)를 추가로 이용해야 함.
-
안드로이드 개발 환경 구축
2.1 ~ 2.4 는 환경구축 및 테스트 과정 안내 이므로 따로 요약 X. 추후 실질 환경 구축 시 교재 참고할 것.
VirtualBox: 윈도우 운영체제에서 안드로이드 플랫폼 소스 코드를 빌드하기 위한 리눅스를 설치하는데 사용하는 가상머신.
Ubutu: 안드로이드 소스 코드를 빌드하기 위해 사용하는 리눅스 운영체제.
Git: 안드로이드 소스 코드 관리에 사용되는 분산 버전 관리 시스템.
Repo: 안드로이드 소스 코드를 손쉽게 다운로드 하기 위해 사용한 파이썬 스크립트.
Eclipse: 안드로이드 애플리케이션 개발 및 디버깅에 사용한 개발 도구.
Android SDK: 안드로이드 애플리케이션 개발에 사용하는 프로그램 및 라이브러리 모음.
ADT Plugin for Eclipse: 안드로이드 애플리케이션 개발 작업을 돕는 유용한 이클립스 플러그인.
devlopment/ide/eclipse/.classpath: 안드로이드 애플리케이션 프레임워크 자바 소스 코드 및 컴파일 된 클래스 파일 경로를 담고 있는 설정 파일.
2.5 애플리케이션 프레임워크 소스 레벨 디버깅
1) 애플리케이션 프레임워크 소스 로딩
- 시스템 소스를 디버깅 하기 위해 이클립스에 프레임워크 소스 불러오기.
- 이 때 안드로이드에 프에림워크의 소스 경로를 모두 모아 놓은 이클립스 설정 파일이 포함되어 있으므로 이클립스에 모든 프레임워크 소스를 하나하나 불러 올 필요 X.
- 디버거 설정은 프로잭트 마우스 오른쪽 버튼 클릭 후 Debug As > Debug Configurations 선택. (교재 p.26)
2) 테스트 예제인 HelloWorld 프레임워크 소스 레벨 디버깅
- 애플리케이션의 시작 지점에 브레이크 포인트 설정. Debug As > Android Application.
- init 프로세스
3.1 init 프로세스의 실행 과정
- init 프로세스의 실행과정: start_kernal() -> init_post() -> run_init_process() -> init 프로세스 실행.
- init_post() 함수에서 execute_command 에 등록된 프로세스 파일의 경로를 가지고 run_init_process() 함수를 호출하여 execve() 시스템콜 호출.
- init 프로세스 정상 실행 위해서는 커널의 부팅 옵션 init = /init.
3.2 init 프로세스의 소스 코드 분석
init 프로세스 4가지 기능: init.rc 파일 분석하여 실행, 자식 프로세스의 종료 처리, 애플리케이션이 디바이스 드라이버에 접근할 때 사용하기 위한 디바이스 노드 파일 생성, 시스템 동작에 필요한 환경 변수 저장하는 프로퍼티 서비스 제공. 시그널 핸들러 등록 후 부팅에 필요한 디렉터리 생성 및 마운트. 디바이스 노드가 위치하는 /dev 디렉터리 생성 후 open_devnull_stdio() 함수(= null 이라는 디바이스 노드 파일 생성, 표준 입력/출력/에러출력 모두 null 장치로 리다이렉션)로 실행 로그 출력을 위한 장치 생성 or log_init() 함수로 출력 장치 생성. parse_config_file() 함수로 init.rc 파일 파싱. device_list() 함수로 정적 디바이스 노드 생성. property_init() 함수로 공유 메모리에 프로퍼티 영역 생성 및 초기화.3.3 init.rc 파일 분석 및 실행
- init.rc 파일이란? 안드로이드 부팅 시 시스템의 환경 설정과 실행할 프로세스를 기술해 놓은 파일. -> init 프로세스가 이를 통해 액션 리스트, 서비스 리스트 생성. 안드로이드의 플랫폼의 소스코드에서 살펴볼 수 있음.3.3.1 액션 리스트
키워드 'on'.
'on init' 시스템 환경변수 등록(루트 파일 시스템 내의 명령어 사용 위한 실행경로, 컴파일 시 필요한 라이브러리 경로),
부팅 시 필요한 디렉터리 생성, 특정 파일에 대한 퍼미션 지정,
시스템 동작과 관련된 디렉터리 마운트(/system, /data). -> 마운트 후 루트 파일 시스템 완성.
루트 파일 시스템? shell 유틸리티, system 디렉터리, data 디렉터리.
'on boot' 애플리케이션 종료조건 설정(Out Of Memory(= 메모리 부족 시 애플리케이션 종료 역할)의 Adjustment Value 지정),
애플리케이션 구동에 필요한 디렉터리 및 파일 퍼미션 설정.
'on property:<name>=<value>'
실행하는 프로세스: 일회성 프로그램, 데몬 프로세스(백그라운드로 구동되면서 애플리케이션이라 시스템 운용에 관여).
형태: service '실행할 프로세스 이름' '프로세스 경로' \n '프로세스 실행 관련 옵션'
3.3.3 init.rc 파싱 코드 분석
이 함수로 분석. 인자로 전달되는 파일을 읽어 연속적인 문자열로 생성 및 열 파싱.
read_file()(메모리 확보, 시작주소 반환), parse_file()(인자로 전달된 파일의 끝까지 파일 각 라인 파싱. 액션 리스트와 서비스 리스트 생성) 로 나뉨.
lookup_keyword()
parse_file() 안에서 사용되는 함수.
각 라인의 첫 단어에 해당하는 keyword_list 구조체 배열에서 배열의 번호 반환.
keyword_list 구조체 배열은 KEYWORD 리스트에 의해 만들어지고, 각 리스트는 KEYWORD 매크로 사용하여 생성.
KEYWORD 매크로 예시: COMMAND(init 프로세스가 실행하는 명령어들. 실행함수와 매핑), SECTION(액션 리스트와 서비스 리스트 구분.)
pares_new_section()
매크로에 의해 구분된 명령어(on, service)를 액션 리스트나 서비스 리스트에 등록.
이 함수를 수행하고 나면 액션 리스트와 서비스 리스트 완성.
3.3.4 액션 리스트 및 서비스 리스트 실행
액션 리스트 drain_action_queue() 함수로 실행.
서비스 리스트 do_class_start() 함수로 실행.