深入理解 Android 卷I
原文地址:http://wiki.jikexueyuan.com/project/deep-android-v1/
第8章 深入理解Surface系統
本章主要內容
· 詳細分析一個Activity的顯示過程。
· 詳細分析Surface。
· 詳細分析SurfaceFlinger。
本章涉及的原始碼檔名及位置:
· ActivityThread.java
framework/base/core/java/android/app/ActivityThread.java
· Activity.java
framework/base/core/java/android/app/Activity.java
· Instrumentation.java
framework/base/core/java/android/app/Instrumentation.java
· PolicyManager.java
frameworks/policies/base/phone/com/android/internal/policy/impl/PolicyManager.java
· Policy.java
frameworks/policies/base/phone/com/android/internal/policy/impl/Policy.java
· PhoneWindow.java
frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindow.java
· Window.java
framework/base/core/java/android/view/Window.java
· WindowManagerImpl
framework/ base/core/java/android/view/WindowManagerImpl.java
· ViewRoot.java
framework/base/core/java/android/view/ViewRoot.java
· Surface.java
framework/base/core/java/android/view/Surface.java
· WindowManagerService.java
framework/base/services/java/com/android/server/WindowManagerService.java
· IWindowSession.aidl
framework/base/core/java/android/view/IWindowSession.aidl
· IWindow.aidl
framework/base/core/java/android/view/IWindow.aidl
· SurfaceSession.java
framework/base/core/java/android/view/SurfaceSession.java
· android_view_Surface.cpp
framework/base/core/jni/android_view_Surface.cpp
· framebuffer_service.c
system/core/adb/framebuffer_service.c
· SurfaceComposerClient.cpp
framework/base/libs/surfaceflinger_client/SurfaceComposerClient.cpp
· SurfaceFlinger.cpp
framework/base/libs/surfaceflinger/SurfaceFlinger.cpp
· ISurfaceComposer.h
framework/base/include/surfaceflinger/ISurfaceComposer.h
· Layer.h
framework/base/include/surfaceflinger/Layer.h
· Layer.cpp
framework/base/libs/surfaceflinger/Layer.cpp
· LayerBase.cpp
framework/base/libs/surfaceflinger/LayerBase.cpp
· Surface.cpp
framework/base/libs/surfaceflinger_client/Surface.cpp
· SharedBufferStack.cpp
framework/base/libs/surfaceflinger_client/SharedBufferStack.cpp
· GraphicBuffer.h
framework/base/include/ui/GraphicBuffer.h
· GraphicBuffer.cpp
framework/base/libs/ui/GraphicBuffer.cpp
· GraphicBufferAllocator.h
framework/base/include/ui/GraphicBufferAllocator.h
· GraphicBufferAllocator.cpp
framework/base/libs/ui/GraphicBufferAllocator.cpp
· GraphicBufferMapper.cpp
framework/base/libs/ui/GraphicBufferMapper.cpp
· Android_natives.h
framework/base/include/ui/egl/Android_natives.h
· android_native_buffer.h
framework/base/include/ui/android_native_buffer.h
· native_handle.h
system/core/include/cutils/native_handle.h
· gralloc.h
hardware/libhardware/include/hardware/gralloc.h
· ISurface.cpp
framework/base/libs/surfaceflinger_client/ISurface.cpp
· DisplayHardware.cpp
framework/base/libs/surfaceflinger/DisplayHardware.cpp
8.1 概述
Surface是繼Audio系統後要破解第二個複雜的系統。它的難度和複雜度遠遠超過了Audio。基於這種情況,本章將集中精力打通Surface系統的“任督二脈”,這任督二脈分別是:
· 任脈:應用程式和Surface的關係。
· 督脈:Surface和SurfaceFlinger之間的關係。
當這二脈打通後,我們就可以自行修煉更高層次的功夫了。圖8-1顯示了這二脈的關係:
圖8-1 Surface系統的任督二脈
其中,左圖是任脈,右圖是督脈。
· 先看左圖。可以發現,不論是使用Skia繪製二維影象,還是用OpenGL繪製三維影象,最終Application都要和Surface互動。Surface就像是UI的畫布,而App則像是在Surface上作畫。所以要想打通任脈,就須破解App和Surface之間的關係。
· 再看右圖。Surface和SurfaceFlinger的關係,很像Audio系統中AudioTrack和AudioFlinger的關係。Surface向SurfaceFlinger提供資料,而SurfaceFlinger則混合資料。所謂打通督脈的關鍵,就是破解Surface和SurfaceFlinger之間的關係。
目標已清楚,讓我們開始“運功”破解程式碼吧!
說明:為書寫方便起見,後文將SurfaceFlinger簡寫為SF。
8.2 一個Activity的顯示
一般來說,應用程式的外表是通過Activity來展示的。那麼,Activity是如何完成介面繪製工作的呢?根據前面所講的知識,應用程式的顯示和Surface有關,那麼具體到Activity上,它和Surface又是什麼關係呢?
本節就來討論這些問題。首先從Activity的建立說起。
我們已經知道了Activity的生命週期,如onCreate、onDestroy等,但大家是否考慮過這樣一個問題:
· 如果沒有建立Activity,那麼onCreate和onDestroy就沒有任何意義,可這個Activity究竟是在哪裡建立的?。
第4章中的“Zygote分裂”一節已講過,Zygote在響應請求後會fork一個子程序,這個子程序是App對應的程序,它的入口函式是ActivityThread類的main函式。ActivityThread類中有一個handleLaunchActivity函式,它就是建立Activity的地方。一起來看這個函式,程式碼如下所示:
[-->ActivityThread.java]
private final voidhandleLaunchActivity(ActivityRecord r, Intent customIntent) {
//①performLaunchActivity返回一個Activity
Activitya = performLaunchActivity(r, customIntent);
if(a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//②呼叫handleResumeActivity
handleResumeActivity(r.token, false, r.isForward);
}
......
}
handleLaunchActivity函式中列出了兩個關鍵點,下面對其分別介紹。
1. 建立Activity
第一個關鍵函式performLaunchActivity返回一個Activity,這個Activity就是App中的那個Activity(僅考慮App中只有一個Activity的情況),它是怎麼建立的呢?其程式碼如下所示:
[-->ActivityThread.java]
private final ActivityperformLaunchActivity(ActivityRecord r,
Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
......//完成一些準備工作
//Activity定義在Activity.java中
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
/*
mInstrumentation為Instrumentation型別,原始檔為Instrumentation.java。
它在newActivity函式中根據Activity的類名通過Java反射機制來建立對應的Activity,
這個函式比較複雜,待會我們再分析它。
*/
activity = mInstrumentation.newActivity(
cl,component.getClassName(), r.intent);
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
}catch (Exception e) {
......
}
try {
Application app =
r.packageInfo.makeApplication(false,mInstrumentation);
if (activity != null) {
//在Activity中getContext函式返回的就是這個ContextImpl型別的物件
ContextImpl appContext = new ContextImpl();
......
//下面這個函式會呼叫Activity的onCreate函式
mInstrumentation.callActivityOnCreate(activity, r.state);
......
return activity;
}
好了,performLaunchActivity函式的作用明白了吧?
· 根據類名以Java反射的方法建立一個Activity。
· 呼叫Activity的onCreate函式,開始SDK中大書特書Activity的生命週期。
那麼,在onCreate函式中,我們一般會做什麼呢?在這個函式中,和UI相關的重要工作就是呼叫setContentView來設定UI的外觀。接下去,需要看handleLaunchActivity中第二個關鍵函式handleResumeActivity。
2. 分析handleResumeActivity
上面已建立好了一個Activity,再來看handleResumeActivity。它的程式碼如下所示:
[-->ActivityThread.java]
final void handleResumeActivity(IBinder token,boolean clearHide,
boolean isForward) {
boolean willBeVisible = !a.mStartedActivity;
if (r.window == null && !a.mFinished&& willBeVisible) {
r.window= r.activity.getWindow();
//①獲得一個View物件
Viewdecor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//②獲得ViewManager物件
ViewManagerwm = a.getWindowManager();
......
//③把剛才的decor物件加入到ViewManager中
wm.addView(decor,l);
}
......//其他處理
}
上面有三個關鍵點。這些關鍵點似乎已經和UI部分(如View、Window)有聯絡了。那麼這些聯絡是在什麼時候建立的呢?在分析上面程式碼中的三個關鍵點之前,請大家想想在前面的過程中,哪些地方會和UI掛上鉤呢?
· 答案就在onCreate函式中,Activity一般都在這個函式中通過setContentView設定UI介面。
看來,必須先分析setContentView,才能繼續後面的征程。
3. 分析setContentView
setContentView有好幾個同名函式,現在只看其中的一個就可以了。程式碼如下所示:
[-->Activity.java]
public void setContentView(View view) {
//getWindow返回的是什麼呢?一起來看看。
getWindow().setContentView(view);
}
public Window getWindow() {
returnmWindow; //返回一個型別為Window的mWindow,它是什麼?
}
上面出現了兩個和UI有關係的類:View和Window[①]。來看SDK文件是怎麼描述這兩個類的。這裡先給出原文描述,然後進行對應翻譯:
· Window:abstract base class for a top-levelwindow look and behavior policy. An instance of this class should be used asthe top-level view added to the window manager. It provides standard UIpolicies such as a background, title area, default key processing, etc.
中文的意思是:Window是一個抽象基類,用於控制頂層視窗的外觀和行為。做為頂層視窗它有什麼特殊的職能呢?即繪製背景和標題欄、預設的按鍵處理等。
這裡面有一句比較關鍵的話:它將做為一個頂層的view加入到Window Manager中。
· View:This class represents the basicbuilding block for user interface components. A View occupies a rectangulararea on the screen and is responsible for drawing and event handling.
View的概念就比較簡單了,它是一個基本的UI單元,佔據螢幕的一塊矩形區域,可用於繪製,並能處理事件。
從上面的View和Window的描述,再加上setContentView的程式碼,我們能想象一下這三者的關係,如圖8-2所示:
圖8-2 Window/View的假想關係圖
根據上面的介紹,大家可能會產生兩個疑問:
· Window是一個抽象類,它實際的物件到底是什麼型別?
· Window Manager究竟是什麼?
如果能有這樣的疑問,就說明我們非常細心了。下面試來解決這兩個問題。
(1)Activity的Window
據上文講解可知,Window是一個抽象類。它實際的物件到底屬於什麼型別?先回到Activity建立的地方去看看。下面正是建立Activity時的程式碼,可當時沒有深入地分析。
activity = mInstrumentation.newActivity(
cl,component.getClassName(), r.intent);
程式碼中呼叫了Instrumentation的newActivity,再去那裡看看。
[-->Instrumentation.java]
public Activity newActivity(Class<?>clazz, Context context,
IBinder token, Application application, Intent intent,
ActivityInfo info, CharSequencetitle, Activity parent,
String id,Object lastNonConfigurationInstance)
throws InstantiationException, IllegalAccessException{
Activity activity = (Activity)clazz.newInstance();
ActivityThread aThread = null;
//關鍵函式attach!!
activity.attach(context, aThread, this, token, application, intent,
info, title,parent, id, lastNonConfigurationInstance,
new Configuration());
return activity;
}
看到關鍵函式attach了吧?Window的真相馬上就要揭曉了,讓我們用咆哮體②來表達內心的激動之情吧!!!!
[-->Activity.java]
final void attach(Context context,ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance,
HashMap<String,Object> lastNonConfigurationChildInstances,
Configuration config) {
......
//利用PolicyManager來建立Window物件
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
......
//建立WindowManager物件
mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
if(mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
//儲存這個WindowManager物件
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
此刻又有一點失望吧?這裡冒出了個PolicyManager類,Window是由它的makeNewWindow函式所建立,因此還必須再去看看這個PolicyManager。
(2)水面下的冰山——PolicyManager
PolicyManager定義於PolicyManager.java檔案,該檔案在一個非常獨立的目錄下,現將其單獨列出來:
· frameworks/policies/base/phone/com/android/internal/policy/impl
注意,上面路徑中的灰色目錄phone是針對智慧手機這種小螢幕的;另外還有一個平級的目錄叫mid,是針對Mid裝置的。mid目錄的程式碼比較少,可能目前還沒有開發完畢。
下面來看這個PolicyManager,它比較簡單。
[-->PolicyManager.java]
public final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static{
//
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
//建立Policy物件
sPolicy = (IPolicy)policyClass.newInstance();
}catch (ClassNotFoundException ex) {
......
}
private PolicyManager() {}
//通過Policy物件的makeNewWindow建立一個Window
publicstatic Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
......
}
這裡有一個單例的sPolicy物件,它是Policy型別,請看它的定義。
(3)真正的Window
Policy型別的定義程式碼如下所示:
[-->Policy.java]
public class Policy implements IPolicy {
private static final String TAG = "PhonePolicy";
private static final String[] preload_classes = {
"com.android.internal.policy.impl.PhoneLayoutInflater",
"com.android.internal.policy.impl.PhoneWindow",
"com.android.internal.policy.impl.PhoneWindow$1",
"com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback",
"com.android.internal.policy.impl.PhoneWindow$DecorView",
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
};
static{
//載入所有的類
for (String s : preload_classes) {
try {
Class.forName(s);
} catch (ClassNotFoundException ex) {
......
}
}
}
public PhoneWindow makeNewWindow(Contextcontext) {
//makeNewWindow返回的是PhoneWindow物件
return new PhoneWindow(context);
}
......
}
至此,終於知道了程式碼:
相關推薦
JNI(深入理解Android卷I)的讀書筆記
一:概述 JNI:Java Native Interface。 作用:連線Java世界和Native世界。Java程式中函式可以呼叫Native語言寫的函式;Native程式中的函式可以呼叫Java層的函式。 二:例項:MediaScanner 2.1 關係: Java層(
深入理解 Android 卷I
原文地址:http://wiki.jikexueyuan.com/project/deep-android-v1/ 第8章 深入理解Surface系統 本章主要內容 · 詳細分析一個Activity的顯示過程。 · 詳細分析Surface
《深入理解Android 卷III》第八章深入理解Android桌布(節選)
第8章 深入理解Android桌布(節選) 本章主要內容: · 討論動態桌布的實現。 · 在動態桌布的基礎上討論靜態桌布的實現。 · 討論WMS對桌布視窗所做的特殊處理。 本章涉及的原始碼檔名及位置: · Wal
《深入理解Android 卷III》第四章 深入理解WindowManagerService
《深入理解Android 卷III》即將釋出,作者是張大偉。此書填補了深入理解Android Framework卷中的一個主要空白,即Android Framework中和UI相關的部分。在一個特別講究顏值的時代,本書分析了Android 4.2中WindowManagerS
[深入理解Android卷二 全文-第三章]深入理解SystemServer
由於《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知識的傳播不應該因為紙質媒介的問題而中斷,所以我將在CSDN部落格中全文轉發這兩本書的全部內容 第3章 深入理解SystemServer本章主要內容:· 分析SystemServer· 分析
《深入理解Android 卷III》推薦序
轉載:https://blog.csdn.net/innost/article/details/47292791《深入理解Android 卷III》即將釋出,作者是張大偉。此書填補了深入理解Android Framework卷中的一個主要空白,即Android Framewo
《深入理解Android 卷III》第五章 深入理解Android輸入系統
《深入理解Android 卷III》即將釋出,作者是張大偉。此書填補了深入理解Android Framework卷中的一個主要空白,即Android Framework中和UI相關的部分。在一個特別講究顏值的時代,本書分析了Android 4.2中WindowManagerS
[深入理解Android卷一全文-第六章]深入理解Binder
由於《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知識的傳播不應該因為紙質媒介的問題而中斷,所以我將在CSDN部落格中全文轉發這兩本書的全部內容。第6章 深入理解Binder本章主要內容· 以MediaServer為切入點,對Binder的工作
[深入理解Android卷一全文-第三章]深入理解init
由於《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知識的傳播不應該因為紙質媒介的問題而中斷,所以我將在CSDN部落格中全文轉發這兩本書的全部內容。第3章 深入理解init本章主要內容· 深入分析init。本章涉及的原始碼檔名及位置下面是本章分
深入理解android(卷1)pdf
下載地址:網盤下載一本以情景方式對Android的原始碼進行深入分析的書。內容廣泛,以對Framework層的分析為主,兼顧Native層和Application層;分析深入,每一部分原始碼的分析都力求透徹;針對性強,注重實際應用開發需求,書中所涵蓋的知識點都是Android
[深入理解Android卷一 全文-第二章]深入理解JNI
由於《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知識的傳播不應該因為紙質媒介的問題而中斷,所以我將在CSDN部落格中全文轉發這兩本書的全部內容。第2章 深入理解JNI本章主要內容· 通過一個例項,介紹JNI技術和在使用中應注意的問題。本章涉
[深入理解Android卷二 全文-第五章]深入理解PowerManagerService
由於《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知識的傳播不應該因為紙質媒介的問題而中斷,所以我將在CSDN部落格中全文轉發這兩本書的全部內容第5章 深入理解PowerManagerService本章主要內容:· 深入分析PowerMana
深入理解Android卷III 第7章 深入理解SystemUI (節選)
多謝華章圖書與鄧凡平先生的幫助,《深入理解Android卷III〉終於上市了。歡迎大家來這裡一起探討文中的問題或與Android系統有關的任何話題。 第7章深入理解SystemUI 本章主要內容: 探討狀態列與導航欄的啟動過程
深入理解 Android Https
前言 大家都知道https相比http增加的是安全性。 怎麼增加安全性呢? 就是加密和解密步驟。 下面來詳細談談對https的理解和在Android中的使用. 兩種加密 加密方式分兩種,對稱加密和非對稱加密。這兩種方式都有自己的優劣勢, https中這兩種方式都採用了。 我們約定S是服務端,C是客戶端,
深入理解Android Gradle
深入理解Android Gradle 標籤(空格分隔): 未分類 原作者真的寫的很棒附上鍊接 新的android開發工具引用了Gradle構建工具,方便了開發者進行構建不同的應用版本以完成不同的需求。(從此多版本不再痛苦) 1. gradle基本語法 新建專案
深入理解Android Bitmap的各種操作
文章目錄 一、Bitmap 1.1 Bitmap的建立 1.1.1 根據已有的Bitmap來建立新Bitmap 1.1.2 通過畫素點陣列建立空的Bitmap 1.1.3 建立縮放的Bit
深入理解Android的startservice和bindservice
一、首先,讓我們確認下什麼是service? service就是android系統中的服務,它有這麼幾個特點:它無法與使用者直接進行互動、它必須由使用者或者其他程式顯式的啟動、它的優先順序比較高,它比處於前臺的應用優先順序低,但是比後臺的其他應用優先順序高,
深入理解Android之View的繪製流程
本篇文章會從原始碼(基於Android 6.0)角度分析Android中View的繪製流程,側重於對整體流程的分析,對一些難以理解的點加以重點闡述,目的是把View繪製的整個流程把握好,而對於特定實現細節則可以日後再對相應原始碼進行研讀。 在進行實際的分析之前,我們先來看下面
Android 深入理解Android中的自定義屬性
1、引言 對於自定義屬性,大家肯定都不陌生,遵循以下幾步,就可以實現: 自定義一個CustomView(extends View )類 編寫values/attrs.xml,在其中編寫styleable和item等標籤元素 在佈局檔案中CustomView使用自定義的屬性(
深入理解Android之Xposed詳解
一、背景Xposed,大名鼎鼎得Xposed,是Android平臺上最負盛名的一個框架。在這個框架下,我們可以載入很多外掛App,這些外掛App可以直接或間接操縱系統層面的東西,比如操縱一些本來只對系統廠商才open的功能(實際上是因為Android系統很多API是不公開的,