2009 제 4 회 Korea Android 세미나 Android Window and View System 2009. 10. 23. www.kandroid.org org 운영자 : 양정수 (yangjeongsoo@gmail.com)
목차 Overview Basic Advancedd Architecture
Overview : Android Platform Stack vs. View/Window System A PPLICATIONS Alarm Dialer SMS/MMS IM Browser Camera Alarm Home Contacts Voice Dial Email Calendar Media Player Albums Clock A PPLICATION F RAMEWORK Activity Manager Window Manager Content Provider View System Notification Manager Package Manager Telephony Manager Resource Manager Location Manager L IBRARIES A NDROID R UNTIME Surface Manager Media Framework SQLite Core Libraries OpenGL ES FreeType WebKit Dalvik Virtual Machine SGL SSL Libc H ARDWARE A BSTRACTION L AYER Graphics Audio Camera Bluetooth GPS Radio(RIL) WiFi L INUX K ERNEL Display Driver Camera Driver Bluetooth Driver Shared Memory Driver Binder (IPC) Driver USB Driver Keypad Driver WiFi Driver Audio Driver Power Management 4 th Korea Android Seminar - www.kandroid.org 3
Overview : Activity & View Hierarchy 아래의내용은 액티비티, 뷰계층구조와레이아웃샘플, 결과화면 에대한간단한요약임. 안드로이드에서화면을구성하는컴포넌트는액티비티이며, 액티비티는 UI를구성하기위해뷰계층구조를사용함. 뷰계층구조는 View 를상속받은 ViewGroup 과이들을각각상속받는 Widget 및 Layout 오브젝트들의계층구조임. public class HelloAndroid extends Activity { @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); } } LinearLayout TextView ImageView 4
Basic : Activity Lifecycle vs. Lifetime 액티비티는아래의그림에서보여지듯이 7개의콜백 (Callback) 메쏘드들로구성된생명주기를가짐. 이들생명주기에는 3개의중첩된루프인, entire, visible, foreground lifetime 루프가존재함. 여기에서우리가주목할부분은, 1) 왜 setcontentview() 시점과액티비티가보여지는상태인 Running 상태가일치하지않는가? 2) 액티비티 visible lifetime에서액티비티를보는것은어떻게가능한가? 일것임. entire visible foreground lifetime lifetime lifetime 5
Basic : View - How Android Draws Views 뷰는자신이보유한직사각형영역에대한그리기를담당한다. 이를위해위치와크기를결정하기위한 측정패스와레이아웃패스 를수행하는콜백메쏘드를가지며, ondraw() 가호출될때해당영역에대한실제그리기를수행함. 측정패스 에서는자신이원하는크기를자신을감싸고있는부모뷰에서요청하며, 레이아웃패스 에서는부모로부터결정된크기와위치를전달받는다. 그리고최종적으로 ondraw() 콜백에서해당영역에대한그리기를수행함. 여기에서의핵심은, ondraw() 에파라미터로전달된 Canvas 란무엇인가?, Canvas 에그리는시점과실제화면에보여 지는시점은일치하는가?, ondraw() 의호출시점은누가결정하는가? 등일것이다. // 측정패스 onmeasure (int widthmeasurespec, int heightmeasurespec) { } // 레이아웃패스 onlayout (boolean changed, int left, int top, int right, int bottom) ){} // 드로잉시점 ondraw (Canvas canvas) { } 6
Basic : Resource - Simple Definition and Functions 안드로이드에서리소스는 /res 디렉토리에물리적으로존재하며, non-code영역에속하는외부요소들이다. 이러한리소스들은코드상에서레퍼런스가능하도록자동으로 R.java 파일내의내부 (inner) 클래스에고유한정수값으로등록된다. (Eclipse ADT에의함 ). 리소스를구성하는많은요소들이 XML 기반이라는사실은매우중요하다. 여기에서사용된대부분의 XML 파일들은 aapt 에의해 deflation의과정을거쳐안드로이드 package에묶여지며, 이는다시 inflation의과정거친후사용된다. ( 여기에서 Deflation 과 Inflation 은일반적인압축알고리즘을이야기하지않음. 개념적으로이해하는것이바람직함.) XML 레이아웃파일및기타 XML 파일들. XML 레이아웃파일에서엘리먼트는 Java 클래스파일에, 애트리뷰트는 Java 메쏘드와밀접하게관련되어있다. 특히, 엘리먼트는 Java 클래스파일에직접적으로맵핑된다. 이것이의미하는바는, Java 클래스의일반적인상속및오버라이딩개념이이곳에도존재한다는것이다. 이것은또한안드로이드에서사용되는레이아웃파일에대한 DTD 또는스키마에대한사전적인정의를어렵게만드는이유이기도하다. 7
Basic : Surface Flinger - Window, Surface and Frame Buffer Surface Flinger 는모든서피스 (Surface) 를프레임버퍼 (Frame Buffer) 디바이스에렌더링하는것으로시스템내의모든서피스들을하나의통합하는역할을담당함. Surface Flinger에의해사용되는서피스는 2D 또는 3D 서피스모두가능하며, 이서피스들은여러개의애플리케이션에기반할수있으며, 중층적인 (Layered) 인구조기반임. 안드로이드에는윈도우 (Window) 란개념이존재함. 모든윈도우는하단에서피스오브젝트를가지고구현되어있음. 그리고이서피스오브젝트는 Surface Flinger에의해프레임버퍼에전달됨. 서피스는더블버퍼링구조를지원함. Back Buffer 는드로잉을위한공간으로사용되며, Front Buffer 는합성 (Composition) 을위해사용된다. 서피스를사용할때 unlockcanvas() 를호출하게하면, Back Buffer에드로잉된결과가 Front Buffer로보내짐. 이것이의미하는바는 Surface Flinger에의해프레임버퍼로결과가전송되어스크린상에보여진다는것을의미함. APP APP Surface Surface SurfaceFlinger FrameBuffer Surface 8
Basic : Display Driver - Double Buffering and Page Flipping 안드로이드는표준리눅스프레임버퍼디바이스인 /dev/fb0 또는 /dev/graphics/fb0 에의존함. 아래의그림은 Double Buffering과 Page Flipping에대한간단한개념설명임. 안드로이드는 Double Buffering에서의 Buffer Copy를최소화하기위해, Back Buffer와 Front Buffer(Primary Surface) 간의 Page Flipping을사용한다. Double Buffering Page Flipping Draw Image Back Buffer Screen Primary Surface Back Buffer Primary Surface Copy (BLT : Block Line Transfer) Screen Image Back Buffer Screen Primary Surface Primary Surface Back Buffer Page Flipping : change primary surface pointer and back buffer pointer for screen video 9
Advanced : Activity & View Hierarchy (1) 아래의두그림중좌측은화면스크린캡쳐이미지이고, 우측은액티비티뷰계층구조전체에대한캡쳐이미지임. 두이미지의차이는 StatusBar에서발생함. ( 우측이미지캡쳐는 SDK tools 디렉토리의 hierarchyviewer 에기초함.) vs 10
Advanced : Activity & View Hierarchy (2) 좌측하단의 xml과뷰계층구조는 setcontentview() 에서사용된 xml 레이아웃및계층구조그림임. 우측하단의뷰계층구조는액티비티가실제보유하고있는뷰계층구조임 ( 우측하단의이계층구조는 SDK tools 디렉토리의 hierarchyviewer 에기초함.) <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent > <TextView android:padding="10dip" android:layout_width="fill_parent" android:layout_height="wrap_content android:text=" 제4회코리아안드로이드세미나 /> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content android:src="@drawable/android_logo /> </LinearLayout> L t vs PhoneWindow$DecorView (FrameLayout) LinearLayout FrameLayout FrameLayout (id/content) LinearLayout TextView (id/title) LinearLayout TextView ImageView TextView ImageView 11
Advanced : Activity & View Hierarchy (3) PRODUCT_POLICY Activity 이곳의그림에언급된 PRODUCT_POLICY는안드로이드 Full 소스코드빌드시에사용되는빌드스크립트이일부임. 현재는 PhoneWindow와 MIDWindow Policy가존재함. PhoneWindow$DecorView (FrameLayout) MIDWindow$DecorView FrameLayout TextView (id/title) LinearLayout FrameLayout (id/content) com.android.internal.r.layout.screen_title./frameworks/base/core/res/res/layout/screen_title.xml <LinearLayout android:orientation="vertical" android:fitssystemwindows="true"> <FrameLayout android:layout_width="fill_parent" android:layout_height="?android:attr/windowtitlesize" i h d i d l " style="?android:attr/windowtitlebackgroundstyle"> <TextView android:id="@android:id/title /> </FrameLayout> <FrameLayout android:id="@android:id/content /> </LinearLayout> 12
Advanced : How Android Draws Views (1) 아래의그림은 Canvas가해당뷰에전달되는과정과뷰가자신의영역을다시그리는과정에대한설명임. 여기서중요한것은뷰계층구조의최상위에 ViewRoot가존재한다는사실임. 또한 ondraw() 가리턴되는시점에서뷰가캔버스에드로잉한결과가화면에나타나는것은아님. 캔버스가화면상에실제로반영되는시점은, ViewRoot, Window, Surface, Surface Flinger 등과연관해서생각해야함. ( 이후에나오는페이지를통해서관련된개념들을정리하는것이요구됨 ) ViewRoot ViewGroup background.draw(canvas) invalidate() draw() ondraw(canvas) dispatchdraw(canvas) View View 13
Advanced : How Android Draws Views (2) - SurfaceView 서피스뷰 (SurfaceView) 는뷰계층구조내에서드로잉전용공간을제공하는뷰에대한특수한서브클래스임. 서피스뷰는뷰가가지는일반적한계, 즉뷰스스로가그리는시점을결정할수없다는것에대한해법이다. 이를위해서피스뷰는뷰계층구조내의드로잉시점 (ondraw() 콜백 ) 시점에해당위치에투명한펀치홀만을유지함. 이투명펀치홀에그리기를위해서피스뷰는서피스홀더와독자적인보조쓰레드를사용함. <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent > <TextView android:text=" 제4회코리아안드로이드세미나 /> <ImageView android:src="@drawable/android_logo /> <SurfaceView android:width= 100dip android:height= 100dip /> </LinearLayout> LinearLayout invalidate() draw()? TextView ImageView SurfaceView Punch Hole 14
Advanced : How Android Draws Views (3) - Window Window 윈도우는애플리케이션의룩앤필과같은일반적인윈도우요소들을명시하는추상클래스임. Window Window 이것은백그라운드, 타이틀영역, 디폴트키프로세싱과같은표준 UI 정책을제공한다. 앞선페이지에서간단히언급된 PhoneWindow 가이러한 Window 에대한구현임. 액티비티, 윈도우, 서피스의관계 액티비티는하나이상의윈도우를가질수있음. Screen 윈도우는하나이상의서피스 (Surface) 를가질수있음. 15
Architecture : Canvas - 2D Drawing Context 캔버스는비트맵 (Bitmap) 또는서피스 (Surface) 오브젝트에대한실질적인비트합성 (Bit Composition) 을담당하는드로잉공간임. 캔버스는다양한형태의 2D 그래픽 API를제공한다. 단, 이것은 OpenGL ES와같은하드웨어가속기를지원하지않음. 캔버스의 Java 베이스클래스는 Canvas이며, 이는안드로이드 2D 그래픽라이브러리인 Skia 그래픽라이브러리에기반한다. 또한 Skia 그래픽라이브러리는안드로이드상에서의 corecg, sgl, skiaagl를구성하는기초가된다. 이중 sgl은 2D 그랙픽을위한것이고, skiaagl은 3D Open GL을위한것이지만현재는사용되지않는듯함. sgl 에서사용되는외부라이브러리에는 gif, jpeg, png, freetype 라이브러리등이있음. Canvas SGL GIF FreeType JPEG PNG Surface 16
Architecture : OpenGL ES - 3D Graphics Library 안드로이드는빠르고복잡한 3D 이미지를사용하기위해 OpenGL ES 라이브러리를제공한다. 이를위해, android.opengl 과 javax.microedition.khronos.opengles 패키지를제공한다. 이러한 java 패키지들은 OpenGL ES의네이티브라이브러리 (wrapper) 인 GLES_CM에기반하며, 이는다시 EGL( 네이티브플랫폼그래픽인터페이스 ) 에기반한다. EGL을구현하는방식은 hardware적인구현과 software적인구현이제공되며, 이를위해 libagl.so( 안드로이드 GL) 과 libhgl.so( 하드웨어 GL) 가사용된다. 아래는 EGL Surface의생성과정임. meglsurface = megl.eglcreatewindowsurface(megldisplay, meglconfig, holder, null); GLSurface sur = eglcreatewindowsurface(dpy, cnf, new EGLNativeWindowSurface(window), base); EGLNativeWindowSurface(const sp<surface>& surface); OpenGL ES EGL hgl agl GPU Pixel Flinger Surface 17
Architecture : Activity, ViewRoot, Window Activity Token Window Manager ViewRoot (Handler) Window Surface Session Window LayoutParams (for window layer) PhoneWindow$DecorView (FrameLayout) LinearLayoutL FrameLayout FrameLayout (id/content) TextView (id/title) 18
Architecture : SurfaceFlinger APP SurfaceFlinger::instantiate() - AddSevice( Surface Flinger..) SurfaceFlinger::readyToRun() Surface - Gather EGL extensions - Create EGL Surface and Map Frame Buffer - Create our OpenGL ES context - Gather OpenGL ES extensions - Init Display Hardware for GPU APP Surface SurfaceFlinger::threadLoop() - Wait for Event - Check for tranaction - Post Surface (if needed) - Post FrameBuffer Surface Flinger Frame Buffer Surface 19
Architecture : ActivityManager vs OOM init.rc # Define the oom_adj values for the classes of processes that can be # killed by the kernel. These are used in ActivityManagerService. setprop ro.foreground_app_adj 0 setprop ro.visible_app_adj 1 setprop ro.secondary_server_adj 2 setprop ro.hidden_app_min_adj 7 setprop ro.content_provider_adj 14 setprop ro.empty_app_adj 15 # Define the memory thresholds at which the above process classes will # be killed. These numbers are in pages (4k). setprop ro.foreground_app_mem 1536 setprop ro.visible_app_mem 2048 setprop ro.secondary_server_mem 4096 setprop ro.hidden_app_mem 5120 setprop ro.content_provider_mem 5632 setprop ro.empty_app_mem 6144 # Write value must be consistent with the above properties. write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15,,,, write /proc/sys/vm/overcommit_memory 1 write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144 # Set init its forked children's oom_adj. write /proc/1/oom_adj -16 Foreground process Visible Process Service Process Background process Empty process Activity Manager OOM Killer /proc/<pid>/oom_adj /proc/<pid>/oom_score 20
감사합니다 21