原文出處——>[Android應用程序UI硬件加速渲染環境初始化過程分析](http://blog.csdn.net/luoshengyang/article/details/45769759)
在Android應用程序中,我們是通過Canvas API來繪制UI元素的。在硬件加速渲染環境中,這些Canvas API調用最終會轉化為Open GL API調用(轉化過程對應用程序來說是透明的)。由于Open GL API調用要求發生在Open GL環境中,因此在每當有新的Activity窗口啟動時,系統都會為其初始化好Open GL環境。這篇文章就詳細分析這個Open GL環境的初始化過程。
Open GL環境也稱為Open GL渲染上下文。一個Open GL渲染上下文只能與一個線程關聯。在一個Open GL渲染上下文創建的Open GL對象一般來說只能在關聯的Open GL線程中操作。這樣就可以避免發生多線程并發訪問發生的沖突問題。這與大多數的UI架構限制UI操作只能發生在UI線程的原理是差不多的。
在Android 5.0之前,Android應用程序的主線程同時也是一個Open GL線程。但是從Android 5.0之后,Android應用程序的Open GL線程就獨立出來了,稱為Render Thread,如圖1所示:
:-: 
圖1 Android應用程序Main Thread和Render Thread
Render Thread有一個Task Queue,Main Thread通過一個代理對象Render Proxy向這個Task Queue發送一個drawFrame命令,從而驅使Render Thread執行一次渲染操作。因此,Android應用程序UI硬件加速渲染環境的初始化過程任務之一就是要創建一個Render Thread。
一個Android應用程序可能存在多個Activity組件。在Android系統中,每一個Activity組件都是一個獨立渲染的窗口。由于一個Android應用程序只有一個Render Thread,因此當Main Thread向Render Thread發出渲染命令時,Render Thread要知道當前要渲染的窗口是什么。從這個角度看,Android應用程序UI硬件加速渲染環境的初始化過程任務之二就是要告訴Render Thread當前要渲染的窗口是什么。
一旦Render Thread知道了當前要渲染的窗口,它就將可以將該窗口綁定到Open GL渲染上下文中去,從而使得后面的渲染操作都是針對被綁定的窗口的,如圖2所示:
:-: 
圖2 綁定窗口到Open GL渲染上下文中
Java層的Activity窗口到了Open GL這一層,被抽象為一個ANativeWindow。將它綁定到Open GL渲染上下文之后,就可以通過eglSwapBuffer函數向SurfaceFlinger服務Dequeue和Queue Graphic Buffer。其中,Dequeue Graphic Buffer是為了在上面進行繪制UI,而Queue Graphic Buffer是為了將繪制好的UI交給Surface Flinger合成和顯示。
接下來,我們就結合源代碼分析Android應用程序UI硬件加速渲染環境的初始化過程,主要的關注點就是創建Render Thread的過程和綁定窗口到Render Thread的過程。
從前面Android應用程序窗口(Activity)的視圖對象(View)的創建過程分析一文可以知道,Activity組件在創建的過程中,也就是在其生命周期函數onCreate的調用過程中,一般會通過調用另外一個成員函數setContentView創建和初始化關聯的窗口視圖,最后通過調用ViewRoot類的成員函數setView完成這一過程。上述文章分析的源碼是Android 2.3版本的。到了Android 4.0之后,ViewRoot類的名字改成了ViewRootImpl,它們的作用仍然一樣的。
Android應用程序UI硬件加速渲染環境的初始化過程是在ViewRootImpl類的成員函數setView開始,如下所示:
~~~
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
......
if (view instanceof RootViewSurfaceTaker) {
mSurfaceHolderCallback =
((RootViewSurfaceTaker)view).willYouTakeTheSurface();
if (mSurfaceHolderCallback != null) {
mSurfaceHolder = new TakenSurfaceHolder();
mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
}
}
......
// If the application owns the surface, don't enable hardware acceleration
if (mSurfaceHolder == null) {
enableHardwareAcceleration(attrs);
}
......
}
}
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewRootImpl.java中。
參數view描述的是當前正在創建的Activity窗口的頂級視圖。如果它實現了RootViewSurfaceTaker接口,并且通過該接口的成員函數willYouTakeTheSurface提供了一個SurfaceHolder.Callback2接口,那么就表明應用程序想自己接管對窗口的一切渲染操作。這樣創建出來的Activity窗口就類似于一個SurfaceView一樣,完全由應用程序自己來控制它的渲染。
基本上我們是不會將一個Activity窗口當作一個SurfaceView來使用的,因此在ViewRootImpl類的成員變量mSurfaceHolder將保持為null值,這樣就會導致ViewRootImpl類的成員函數enableHardwareAcceleration被調用為判斷是否需要為當前創建的Activity窗口啟用硬件加速渲染。
ViewRootImpl類的成員函數enableHardwareAcceleration的實現如下所示:
~~~
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
......
// Try to enable hardware acceleration if requested
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
if (hardwareAccelerated) {
if (!HardwareRenderer.isAvailable()) {
return;
}
// Persistent processes (including the system) should not do
// accelerated rendering on low-end devices. In that case,
// sRendererDisabled will be set. In addition, the system process
// itself should never do accelerated rendering. In that case, both
// sRendererDisabled and sSystemRendererDisabled are set. When
// sSystemRendererDisabled is set, PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED
// can be used by code on the system process to escape that and enable
// HW accelerated drawing. (This is basically for the lock screen.)
final boolean fakeHwAccelerated = (attrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
final boolean forceHwAccelerated = (attrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
if (fakeHwAccelerated) {
// This is exclusively for the preview windows the window manager
// shows for launching applications, so they will look more like
// the app being launched.
mAttachInfo.mHardwareAccelerationRequested = true;
} else if (!HardwareRenderer.sRendererDisabled
|| (HardwareRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
.......
mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
if (mAttachInfo.mHardwareRenderer != null) {
.......
mAttachInfo.mHardwareAccelerated =
mAttachInfo.mHardwareAccelerationRequested = true;
}
}
}
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewRootImpl.java中。
雖然硬件加速渲染是個好東西,但是也不是每一個需要繪制UI的進程都必需的。這樣做是考慮到兩個因素。第一個因素是并不是所有的Canvas API都可以被GPU支持。如果應用程序使用到了這些不被GPU支持的API,那么就需要禁用硬件加速渲染。第二個因素是支持硬件加速渲染的代價是增加了內存開銷。例如,只是硬件加速渲染環境初始化這一操作,就要花掉8M的內存。因此,對于兩類進程就不是很適合使用硬件加速渲染。
第一類進程是Persistent進程。Persistent進程是一種常駐進程,它們的優先級別很高,即使在內存緊張的時候也不會被AMS殺掉。對于低內存設備,這類進程是不適合使用硬件加速渲染的。在這種情況下,它們會將HardwareRenderer類的靜態成員變量sRendererDisabled設置為true,表明要禁用硬件加速渲染。這里順便提一下,一個應用程序進程可以在AndroidManifest.xml文件將Application標簽的persistent屬性設置為true來將自己設置為Persistent進程,不過只有系統級別的應用設置才有效。類似的進程有Phone、Bluetooth和Nfc等應用。
第二類進程是System進程。System進程有很多線程是需要顯示UI的。這些UI一般都是比較簡單的,并且System進程也像Persistent進程一樣,在內存緊張時是無法殺掉的,因此它們完全沒有必要通過硬件加速來渲染。于是,System進程就會將HardwareRenderer類的靜態成員變量sRendererDisabled和sSystemRendererDisabled都會被設置為true,表示它要禁用硬件加速渲染。
對于System進程,有兩種UI需要特殊處理。第一種UI是Starting Window。當一個Activity啟動時,如果它的宿主進程還沒有創建,那么在等待其宿主進程創建的過程中,System進程就會根據該Activity窗口設置的Theme顯示一個Starting Window,也稱為Preview Window。由于System進程是禁用了硬件加速渲染的,因此Starting Window是通過軟件方式渲染的。但是為了使得Starting Window的渲染更像它對應的Activity窗口,我們將用來描述Starting Window屬性的一個AttachInfo對象的成員變量mHardwareAccelerationRequested的值設置為true。這將會使得Starting Window的view_state_accelerated屬性設置為true。該屬性一旦被設置為true,將會使得Starting Window的另一屬性colorBackgroundCacheHint被忽略。屬性colorBackgroundCacheHint被忽略之后,Starting Window在繪制的過程中將不會被緩存。使用了硬件加速渲染的Activity窗口在渲染的過程中也是不會被緩存的。這就使得它們的渲染行為保持一致。Starting Window的這一特性是通過將參數attrs指向的一個WindowManager.LayoutParams對象的成員變量privateFlags的位WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED設置為1來描述的。
第二種UI是鎖屏界面。鎖屏界面是一個例外,它允許使用硬件加速渲染。但是System進程又表明了它要禁用硬件加速渲染,這時候就通過將參數attrs指向的一個WindowManager.LayoutParams對象的成員變量privateFlags的位WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED設置為1來強調鎖屏界面不受System進程禁用硬件加速的限制。
除了上面提到的兩類進程以及一些特殊的UI,其余的就根據Activity窗口自己是否請求了硬件加速渲染而決定是否要為其開啟硬件加速。在默認情況下,Activity窗口是請求硬件加速渲染的,也就是參數attrs指向的一個WindowManager.LayoutParams對象的成員變量flags的位WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED是被設置為1的。不過即便如此,也是要設備本身支持硬件加速渲染才行。判斷設備是否設置硬件加速渲染可以通過調用HardwareRenderer類的靜態成員函數isAvailable來獲得。
最后,如果當前創建的窗口支持硬件加速渲染,那么就會調用HardwareRenderer類的靜態成員函數create創建一個HardwareRenderer對象,并且保存在與該窗口關聯的一個AttachInfo對象的成員變量的成員變量mHardwareRenderer對象。這個HardwareRenderer對象以后將負責執行窗口硬件加速渲染的相關操作。
HardwareRenderer類的靜態成員函數create的實現如下所示:
~~~
public abstract class HardwareRenderer {
......
static HardwareRenderer create(Context context, boolean translucent) {
HardwareRenderer renderer = null;
if (GLES20Canvas.isAvailable()) {
renderer = new ThreadedRenderer(context, translucent);
}
return renderer;
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/HardwareRenderer.java。
從這里就可以看到,在設備支持Open GL ES 2.0的情況下,HardwareRenderer類的靜態成員函數create創建的實際上是一個ThreadedRenderer對象。該ThreadedRenderer對象是從HardwareRenderer類繼承下來的。
接下來我們就繼續分析ThreadedRenderer對象的創建過程,如下所示:
~~~
public class ThreadedRenderer extends HardwareRenderer {
......
private long mNativeProxy;
......
private RenderNode mRootNode;
......
ThreadedRenderer(Context context, boolean translucent) {
......
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
......
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
AtlasInitializer.sInstance.init(context, mNativeProxy);
......
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ThreadedRenderer.java。
在創建ThreadedRenderer對象的過程中,最主要的是做了三件事情:
1. 調用ThreadedRenderer類的成員函數nCreateRootRenderNode在Native層創建了一個Render Node,并且通過Java層的RenderNode類的靜態成員函數adopt將其封裝在一個Java層的Render Node中。這個Render Node即為窗口的Root Render Node。
2. 調用ThreadedRenderer類的成員函數nCreateProxy在Native層創建了一個Render Proxy對象。該Render Proxy對象以后將負責從Main Thread向Render Thread發送命令。
3. 調用AtlasInitializer類的成員函數init初始化一個系統預加載資源的地圖集。通過這個地圖集,可以優化資源的內存使用。
關于系統預加載資源地圖集,我們在下一篇文章中再詳細分析,這里我們主要關注窗口的Root Render Node以及在Main Thread線程中使用的Render Proxy對象的創建過程。
窗口的Root Render Node是通過調用ThreadedRenderer類的成員函數nCreateRootRenderNode創建的。這是一個JNI函數,由Native層的函數android_view_ThreadedRenderer_createRootRenderNode實現,如下所示:
~~~
static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
RootRenderNode* node = new RootRenderNode(env);
node->incStrong(0);
node->setName("RootRenderNode");
return reinterpret_cast<jlong>(node);
}
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
從這里就可以看出,窗口在Native層的Root Render Node實際上是一個RootRenderNode對象。
窗口在Main Thread線程中使用的Render Proxy對象是通過調用ThreadedRenderer類的成員函數nCreateProxy創建的。這是一個JNI函數,由Native層的函數android_view_ThreadedRenderer_createProxy實現,如下所示:
~~~
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
jboolean translucent, jlong rootRenderNodePtr) {
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
ContextFactoryImpl factory(rootRenderNode);
return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
}
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
參數rootRenderNodePtr指向前面創建的RootRenderNode對象。有了這個RootRenderNode對象之后,函數android_view_ThreadedRenderer_createProxy就創建了一個RenderProxy對象。
RenderProxy對象的創建過程如下所示:
~~~
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
: mRenderThread(RenderThread::getInstance())
, mContext(0) {
SETUP_TASK(createContext);
args->translucent = translucent;
args->rootRenderNode = rootRenderNode;
args->thread = &mRenderThread;
args->contextFactory = contextFactory;
mContext = (CanvasContext*) postAndWait(task);
mDrawFrameTask.setContext(&mRenderThread, mContext);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderProxy.cpp中。
RenderProxy類有三個重要的成員變量mRenderThread、mContext和mDrawFrameTask,它們的類型分別為RenderThread、CanvasContext和DrawFrameTask。其中,mRenderThread描述的就是Render Thread,mContext描述的是一個畫布上下文,mDrawFrameTask描述的是一個用來執行渲染任務的Task。接下來我們就重點分析這三個成員變量的初始化過程。
RenderProxy類的成員變量mRenderThread指向的Render Thread是通過調用RenderThread類的靜態成員函數getInstance獲得的。從名字我們就可以看出,RenderThread類的靜態成員函數getInstance返回的是一個RenderThread單例。也就是說,在一個Android應用程序進程中,只有一個Render Thread存在。
為了更好地了解Render Thread是如何運行的,我們繼續分析Render Thread的創建過程,如下所示:
~~~
RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
...... {
mFrameCallbackTask = new DispatchFrameCallbacks(this);
mLooper = new Looper(false);
run("RenderThread");
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
RenderThread類的成員變量mFrameCallbackTask指向一個DispatchFrameCallbacks對象,用來描述一個幀繪制任務。下面描述Render Thread的運行模型時,我們再詳細分析。
RenderThread類的成員變量mLooper指向一個Looper對象,Render Thread通過它來創建一個消息驅動運行模型,類似于Main Thread的消息驅動運行模型。關于Looper的實現,可以參考前面Android應用程序消息處理機制(Looper、Handler)分析一文。
RenderThread類是從Thread類繼承下來的,當我們調用它的成員函數run的時候,就會創建一個新的線程。這個新的線程的入口點函數為RenderThread類的成員函數threadLoop,它的實現如下所示:
~~~
bool RenderThread::threadLoop() {
.......
initThreadLocals();
int timeoutMillis = -1;
for (;;) {
int result = mLooper->pollOnce(timeoutMillis);
......
nsecs_t nextWakeup;
// Process our queue, if we have anything
while (RenderTask* task = nextTask(&nextWakeup)) {
task->run();
// task may have deleted itself, do not reference it again
}
if (nextWakeup == LLONG_MAX) {
timeoutMillis = -1;
} else {
nsecs_t timeoutNanos = nextWakeup - systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = nanoseconds_to_milliseconds(timeoutNanos);
if (timeoutMillis < 0) {
timeoutMillis = 0;
}
}
if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
drainDisplayEventQueue(true);
mFrameCallbacks.insert(
mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end());
mPendingRegistrationFrameCallbacks.clear();
requestVsync();
}
}
return false;
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
這里我們就可以看到Render Thread的運行模型:
1. 空閑的時候,Render Thread就睡眠在成員變量mLooper指向的一個Looper對象的成員函數pollOnce中。
2. 當其它線程需要調度Render Thread,就會向它的任務隊列增加一個任務,然后喚醒Render Thread進行處理。Render Thread通過成員函數nextTask獲得需要處理的任務,并且調用它的成員函數run進行處理。
RenderThread類的成員函數nextTask的實現如下所示:
~~~
RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
AutoMutex _lock(mLock);
RenderTask* next = mQueue.peek();
if (!next) {
mNextWakeup = LLONG_MAX;
} else {
mNextWakeup = next->mRunAt;
// Most tasks won't be delayed, so avoid unnecessary systemTime() calls
if (next->mRunAt <= 0 || next->mRunAt <= systemTime(SYSTEM_TIME_MONOTONIC)) {
next = mQueue.next();
} else {
next = 0;
}
}
if (nextWakeup) {
*nextWakeup = mNextWakeup;
}
return next;
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
RenderThread類的成員變量mQueue描述的是一個Task Queue。每一個Task都是用一個RenderTask對象來描述。同時,RenderTask類有一個成員變量mRunAt,用來表明Task的執行時間。這樣,保存在Task Queue的Task就可以按照執行時間從先到后的順序排序。于是,RenderThread類的成員函數nextTask通過判斷排在隊列頭的Task的執行時間是否小于等于當前時間,就可以知道當前是否有Task需要執行。如果有Task需要執行的話,就將它返回給調用者。
RenderThread類的成員函數nextTask除了返回下一個要執行的Task之外,還會通過參數nextWakeup返回下一個要執行的Task的執行時間。這個時間同時也會記錄在RenderThread類的成員變量mNextWakeup中。注意,下一個要執行的Task可能是馬上就要執行的,也有可能是由于執行時間還未到而不能執行的Task。返回這個時間的意義是使得Render Thread可以準確計算下一次需要進入睡眠狀態的時間。這個計算可以回過頭去看前面分析的RenderThread類的成員函數threadLoop。
注意,如果沒有下一個任務可以執行,那么RenderThread類的成員函數nextTask通過參數nextWakeup返回的值為LLONG_MAX,表示Render Thread接下來無限期進入睡眠狀態,直到被其它線程喚醒為止。
RenderThread類提供了queue、queueAtFront和queueDelayed三個成員函數向Task Queue增加一個Task,它們的實現如下所示:
~~~
void RenderThread::queue(RenderTask* task) {
AutoMutex _lock(mLock);
mQueue.queue(task);
if (mNextWakeup && task->mRunAt < mNextWakeup) {
mNextWakeup = 0;
mLooper->wake();
}
}
void RenderThread::queueAtFront(RenderTask* task) {
AutoMutex _lock(mLock);
mQueue.queueAtFront(task);
mLooper->wake();
}
void RenderThread::queueDelayed(RenderTask* task, int delayMs) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
task->mRunAt = now + milliseconds_to_nanoseconds(delayMs);
queue(task);
}
~~~
這三個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
其中, RenderThread類的成員函數queue按照執行時間將參數task描述的Task排列在Task Queue中,并且如果該Task的執行時間小于之前記錄的下一個要執行任務的執行時間,就會馬上喚醒Render Thread來處理;RenderThread類的成員函數queue將參數task描述的Task排列在Task Queue的頭部,并且馬上喚醒Render Thread來處理;RenderThread類的成員函數queueDelayed指定參數task描述的Task的執行時間為當前時間之后的delayMs毫秒。
理解了Render Thread的Task Queue之后,回到RenderThread類的成員函數threadLoop中,我們再來看Render Thread在進入無限循環之前調用的RenderThread類的成員函數initThreadLocals,它的實現如下所示:
~~~
void RenderThread::initThreadLocals() {
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
mRenderState = new RenderState();
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
RenderThread類的成員函數initThreadLocals首先調用另外一個成員函數initializeDisplayEventReceiver創建和初始化一個DisplayEventReceiver對象,用來接收Vsync信號。接著又會分別創建一個EglManager對象和一個RenderState對象,并且保存在成員變量mEglManager和mRenderState中。前者用在初始化Open GL渲染上下文需要用到,而后者用來記錄Render Thread當前的一些渲染狀態。
接下來我們主要關注DisplayEventReceiver對象的創建和初始化過程,即RenderThread類的成員函數initializeDisplayEventReceiver的實現,如下所示:
~~~
void RenderThread::initializeDisplayEventReceiver() {
......
mDisplayEventReceiver = new DisplayEventReceiver();
......
// Register the FD
mLooper->addFd(mDisplayEventReceiver->getFd(), 0,
Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
創建的DisplayEventReceiver對象關聯的文件描述符被注冊到了Render Thread的消息循環中。這意味著屏幕產生Vsync信號時,SurfaceFlinger服務(Vsync信號由SurfaceFlinger服務進行管理和分發)會通過上述文件描述符號喚醒Render Thread。這時候Render Thread就會調用RenderThread類的靜態成員函數displayEventReceiverCallback。
RenderThread類的靜態成員函數displayEventReceiverCallback的實現如下所示:
~~~
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
......
reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
return 1; // keep the callback
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
RenderThread類的靜態成員函數displayEventReceiverCallback調用RenderThread類的成員函數drainDisplayEventQueue來處理Vsync信號,后者的實現如下所示:
~~~
void RenderThread::drainDisplayEventQueue(bool skipCallbacks) {
......
nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
if (vsyncEvent > 0) {
mVsyncRequested = false;
mTimeLord.vsyncReceived(vsyncEvent);
if (!skipCallbacks && !mFrameCallbackTaskPending) {
......
mFrameCallbackTaskPending = true;
queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY);
}
}
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
RenderThread類的成員函數drainDisplayEventQueue首先調用另外一個成員函數latestVsyncEvent獲得最新發出的Vsync信號的時間。如果這個時間值大于0,那么就表明這是一個有效的Vsync信號。在這種情況下,就將RenderThread類的成員變量mVsyncRequested設置為false,表示上次發出的Vsync信號接收請求已經獲得。
最后,如果參數skipCallbacks的值等于false,那么就表示需要將RenderThread類的成員變量mFrameCallbackTask指向的一個類型為DispatchFrameCallbacks的Task添加到Render Thread的Task Queue去處理。但是這時候如果RenderThread類的成員變量mFrameCallbackTaskPending的值也等于true,就表示該Task已經添加到Render Thread的Task Queue去了,因此就不再用重復添加。
RenderThread類的成員變量mFrameCallbackTask描述的Task是用來做什么的呢?原來就是用來顯示動畫的。當Java層注冊一個動畫類型的Render Node到Render Thread時,一個類型為IFrameCallback的回調接口就會通過RenderThread類的成員函數postFrameCallback注冊到Render Thread的一個Pending Registration Frame Callbacks列表中,如下所示:
~~~
void RenderThread::postFrameCallback(IFrameCallback* callback) {
mPendingRegistrationFrameCallbacks.insert(callback);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
Render Thread的Pending Registration Frame Callbacks列表由RenderThread類的成員變量mPendingRegistrationFrameCallbacks描述。
當Pending Registration Frame Callbacks列表不為空時,每次Vsync信號到來時,Render Thread都會通過RenderThread類的成員變量mFrameCallbackTask描述的一個Task來執行它,這樣就相當于是將動畫的每一幀都同步到Vsync信號來顯示。這也是為什么RenderThread類的成員函數drainDisplayEventQueue每次被調用要檢查是否需要將成員變量mFrameCallbackTask描述的一個Task添加到Render Thread的Task Queue的原因。
當RenderThread類的成員變量mFrameCallbackTask描述的Task的類型為DispatchFrameCallbacks,當它被調度執行時,它的成員函數run就會被調用,如下所示:
~~~
class DispatchFrameCallbacks : public RenderTask {
private:
RenderThread* mRenderThread;
public:
DispatchFrameCallbacks(RenderThread* rt) : mRenderThread(rt) {}
virtual void run() {
mRenderThread->dispatchFrameCallbacks();
}
};
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
DispatchFrameCallbacks類的成員函數run調用了RenderThread類的成員函數dispatchFrameCallbacks來執行注冊到Pending Registration Frame Callbacks列表中的IFrameCallback回調接口,如下所示:
~~~
void RenderThread::dispatchFrameCallbacks() {
ATRACE_CALL();
mFrameCallbackTaskPending = false;
std::set<IFrameCallback*> callbacks;
mFrameCallbacks.swap(callbacks);
for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) {
(*it)->doFrame();
}
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderThread.cpp中。
我們回過頭來看前面分析的RenderThread類的成員函數threadLoop,每當Render Thread被喚醒時,它都會檢查Pending Registration Frame Callbacks列表是否不為空。如果不為空,那么就會將保存在里面的IFrameCallback回調接口轉移至由RenderThread類的成員變量mFrameCallbacks描述的另外一個IFrameCallback回調接口列表中,并且調用RenderThread類的另外一個成員函數requestVsync請求SurfaceFlinger服務在下一個Vsync信號到來時通知Render Thread,以便Render Thread可以執行剛才被轉移的IFrameCallback回調接口。
現在既然下一個Vsync信號已經到來,因此RenderThread類的成員函數dispatchFrameCallbacks就執行所有轉移至保存在成員變量mFrameCallbacks描述的IFrameCallback回調接口列表中的IFrameCallback接口,即調用它們的成員函數doFrame。
總結來說,Render Thread在運行時主要是做以下兩件事情:
1. 執行Task Queue的任務,這些Task一般就是由Main Thread發送過來的,例如,Main Thread通過發送一個Draw Frame Task給Render Thread的Task Queue中,請求Render Thread渲染窗口的下一幀。
2. 執行Pending Registration Frame Callbacks列表的IFrameCallback回調接口。每一個IFrameCallback回調接口代表的是一個動畫幀,這些動畫幀被同步到Vsync信號到來由Render Thread自動執行。具體來說,就是每當Vsync信號到來時,就將一個類型為DispatchFrameCallbacks的Task添加到Render Thread的Task Queue去等待調度。一旦該Task被調度,就可以在Render Thread中執行注冊在Pending Registration Frame Callbacks列表中的IFrameCallback回調接口了。
在后面的文章中,我們還會繼續分析上述這兩件事情的詳細執行過程。
了解了Render Thread的創建過程之后,回到RenderProxy類的構造函數中,接下來我們繼續分析它的成員變量mContext的初始化過程,也就是畫布上下文的初始化過程。這是通過向Render Thread發送一個createContext命令來完成的。為了方便描述,我們將相關的代碼列出來,如下所示:
~~~
#define ARGS(method) method ## Args
#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
typedef struct { \
a1; a2; a3; a4; a5; a6; a7; a8; \
} ARGS(name); \
static void* Bridge_ ## name(ARGS(name)* args)
#define SETUP_TASK(method) \
.......
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
return new CanvasContext(*args->thread, args->translucent,
args->rootRenderNode, args->contextFactory);
}
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
...... {
SETUP_TASK(createContext);
args->translucent = translucent;
args->rootRenderNode = rootRenderNode;
args->thread = &mRenderThread;
args->contextFactory = contextFactory;
mContext = (CanvasContext*) postAndWait(task);
......
}
~~~
這些代碼片斷定義在文件frameworks/base/libs/hwui/renderthread/RenderProxy.cpp。
這是一個典型的Main Thread通過Render Proxy向Render Thread請求執行一個命令的流程,在后面的文章中,碰到類型的代碼時,我們就將忽略中間的封裝環節,直接分析命令的執行過程。
我們首先看宏SETUP_TASK,它需要一個函數作為參數。這個函數通過CREATE_BRIDGEX來聲明,其中X是一個數字,數字的大小就等于函數需要的參數的個數。例如,通過CREATE_BRIDGE4聲明的函數有4個參數。在上面的代碼段中,我們通過CREATE_BRIDGE4宏聲明了一個createContext函數。
宏SETUP_TASK的作用創建一個類型MethodInvokeRenderTask的Task。這個Task關聯有一個由CREATE_BRIDGEX宏聲明的函數。例如,SETUP_TASK(createContext)創建的MethodInvokeRenderTask關聯的函數是由CREATE_BRIDGE4聲明的函數createContext。這個Task最終會通過RenderProxy類的成員函數postAndWait添加到Render Thread的Task Queue中,如下所示:
~~~
void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
void* retval;
task->setReturnPtr(&retval);
SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
AutoMutex _lock(mSyncMutex);
mRenderThread.queue(&syncTask);
mSyncCondition.wait(mSyncMutex);
return retval;
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderProxy.cpp。
RenderProxy類的成員函數postAndWait除了會將參數task描述MethodInvokeRenderTask描述的Task添加到Render Thread的Task Queue之外,還會等待該Task執行完成之后才返回。也就是說,這是一個從Main Thread到Render Thread的同步調用過程。
當MethodInvokeRenderTask被執行時,它所關聯的函數就會被調用。例如,在我們這個情景中,通過CREATE_BRIDGE4聲明的函數createContext就會被執行。注意,這時候函數createContext是在Render Thread中執行的,它主要就是創建一個CanvasContext對象,用來描述Render Thread的畫布上下文。這個畫布上下文接下來在Render Thread中綁定窗口時會用到,到時候我們就可以更清楚地看到它的作用。
回到RenderProxy類的構造函數中,接下來我們繼續分析它的成員變量mDrawFrameTask的初始化過程。RenderProxy類的成員變量mDrawFrameTask描述的是一個Draw Frame Task,Main Thread每次都是通過它來向Render Thread發出渲染下一幀的命令的。
對Draw Frame Task的初始化很簡單,主要是將前面已經獲得的RenderThread對象和CanvasContext對象保存在它內部,以便以后它可以直接使用相關的功能,這是通過調用DrawFrameTask類的成員函數setContext實現的,如下所示:
~~~
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) {
mRenderThread = thread;
mContext = context;
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp中。
這樣,一個RenderProxy對象的創建過程就分析完成了,從中我們也看到Render Thread的創建過程和運行模型,以及Render Proxy與Render Thread的交互模型,總結來說:
1. RenderProxy內部有一個成員變量mRenderThread,它指向的是一個RenderThread對象,通過它可以向Render Thread線程發送命令。
2. RenderProxy內部有一個成員變量mContext,它指向的是一個CanvasContext對象,Render Thread的渲染工作就是通過它來完成的。
3. RenderProxy內部有一個成員變量mDrawFrameTask,它指向的是一個DrawFrameTask對象,Main Thread通過它向Render Thread線程發送渲染下一幀的命令。
接下來我們繼續分析Android應用程序UI硬件加速渲染環境初始化的另一個主要任務--綁定窗口到Render Thread中。
從前面Android應用程序窗口(Activity)的測量(Measure)、布局(Layout)和繪制(Draw)過程分析這篇文章可以知道,Activity窗口的繪制流程是在ViewRoot(Impl)類的成員函數performTraversals發起的。在繪制之前,首先要獲得一個Surface。這個Surface描述的就是一個窗口。因此,一旦獲得了對應的Surface,就需要將它綁定到Render Thread中,如下所示:
~~~
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
private void performTraversals() {
......
if (mFirst || windowShouldResize || insetsChanged ||
viewVisibilityChanged || params != null) {
......
try {
......
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
......
if (!hadSurface) {
if (mSurface.isValid()) {
......
if (mAttachInfo.mHardwareRenderer != null) {
try {
hwInitialized = mAttachInfo.mHardwareRenderer.initialize(
mSurface);
} catch (OutOfResourcesException e) {
......
}
}
}
}
......
} catch (RemoteException e) {
}
......
}
if (!cancelDraw && !newSurface) {
if (!skipDraw || mReportNextDraw) {
......
performDraw();
}
}
......
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewRootImpl.java中。
當前Activity窗口對應的Surface是通過調用ViewRootImpl類的成員函數relayoutWindow向WindowManagerService服務請求創建和返回的,并且保存在ViewRootImpl類的成員變量mSurface中。如果這個Surface是新創建的,那么就會調用ViewRootImpl類的成員變量mAttachInfo指向的一個AttachInfo對象的成員變量mHardwareRenderer描述的一個HardwareRenderer對象的成員函數initialize將它綁定到Render Thread中。最后,如果需要繪制當前的Activity窗口,那會調用ViewRootImpl類的另外一個成員函數performDraw進行繪制。
這里我們只關注綁定窗口對應的Surface到Render Thread的過程。從前面的分析可以知道,ViewRootImpl類的成員變量mAttachInfo指向的一個AttachInfo對象的成員變量mHardwareRenderer保存的實際上是一個ThreadedRenderer對象,它的成員函數initialize的實現如下所示:
~~~
public class ThreadedRenderer extends HardwareRenderer {
......
@Override
boolean initialize(Surface surface) throws OutOfResourcesException {
mInitialized = true;
......
boolean status = nInitialize(mNativeProxy, surface);
......
return status;
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ThreadedRenderer.java中。
ThreadedRenderer類的成員函數initialize首先將成員變量mInitialized的值設置為true,表明它接下來已經綁定過Surface到Render Thread了,接著再調用另外一個成員函數nInitialize執行真正的綁定工作。
ThreadedRenderer類的成員函數nInitialize是一個JNI函數,由Native層的函數android_view_ThreadedRenderer_initialize實現,如下所示:
~~~
static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jsurface) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
return proxy->initialize(window);
}
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
參數proxyPtr描述的就是之前所創建的一個RenderProxy對象,而參數jsurface描述的是要綁定給Render Thread的Java層的Surface。前面提到,Java層的Surface在Native層對應的是一個ANativeWindow。我們可以通過函數android_view_Surface_getNativeWindow來獲得一個Java層的Surface在Native層對應的ANativeWindow。
接下來,就可以通過RenderProxy類的成員函數initialize將前面獲得的ANativeWindow綁定到Render Thread中,如下所示:
~~~
CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
return (void*) args->context->initialize(args->window);
}
bool RenderProxy::initialize(const sp<ANativeWindow>& window) {
SETUP_TASK(initialize);
args->context = mContext;
args->window = window.get();
return (bool) postAndWait(task);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderProxy.cpp中。
從前面的分析可以知道,RenderProxy類的成員函數initialize向Render Thread的Task Queue發送了一個Task。當這個Task在Render Thread中執行時,由宏CREATE_BRIDGE2聲明的函數initialize就會被執行。
在由宏CREATE_BRIDGE2聲明的函數initialize中,參數context指向的是RenderProxy類的成員變量mContext指向的一個CanvasContext對象,而參數window指向的ANativeWindow就是要綁定到Render Thread的ANativeWindow。
由宏CREATE_BRIDGE2聲明的函數initialize通過調用參數context指向的CanvasContext對象的成員函數initialize來綁定參數window指向的ANativeWindow,如下所示:
~~~
bool CanvasContext::initialize(ANativeWindow* window) {
setSurface(window);
if (mCanvas) return false;
mCanvas = new OpenGLRenderer(mRenderThread.renderState());
......
return true;
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/CanvasContext.cpp中。
CanvasContext類的成員函數initialize通過調用另外一個成員函數setSurface來綁定參數window描述的ANativeWindow到Render Thread中。綁定完成之后,如果CanvasContext類的成員變量mCanvas等于NULL,那么就說明負責執行Open GL渲染命令的一個OpenGLRenderer對象還沒創建。在這種情況下,就創建一個OpenGLRenderer對象,并且保存在CanvasContext類的成員變量mCanvas中,以便后面可以用來執行Open GL相關操作。
CanvasContext類的成員函數setSurface的實現如下所示:
~~~
void CanvasContext::setSurface(ANativeWindow* window) {
mNativeWindow = window;
if (mEglSurface != EGL_NO_SURFACE) {
mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
}
if (window) {
mEglSurface = mEglManager.createSurface(window);
}
if (mEglSurface != EGL_NO_SURFACE) {
......
mHaveNewSurface = true;
makeCurrent();
}
......
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/CanvasContext.cpp中。
每一個Open GL渲染上下文都需要關聯有一個EGL Surface。這個EGL Surface描述的是一個繪圖表面,它封裝的實際上是一個ANativeWindow。有了這個EGL Surface之后,我們在執行Open GL命令的時候,才能確定這些命令是作用在哪個窗口上。
CanvasContext類的成員變量mEglManager實際上是指向前面我們分析RenderThread類的成員函數initThreadLocals時創建的一個EglManager對象。通過調用這個EglManager對象的成員函數createSurface就可以將參數window描述的ANativeWindow封裝成一個EGL Surface。
EGL Surface創建成功之后,就可以調用CanvasContext類的成員函數makeCurrent將它綁定到Render Thread的Open GL渲染上下文來,如下所示:
~~~
void CanvasContext::makeCurrent() {
// TODO: Figure out why this workaround is needed, see b/13913604
// In the meantime this matches the behavior of GLRenderer, so it is not a regression
mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/CanvasContext.cpp中。
從這里就可以看到,將一個EGL Surface綁定到Render Thread的Open GL渲染上下文中是通過CanvasContext類的成員變量mEglManager指向的一個EglManager對象的成員函數makeCurrent來完成的。實際上就是通過EGL函數建立了從Open GL到底層OS圖形系統的橋梁。這一點應該怎么理解呢?Open GL是一套與OS無關的規范,不過當它在一個具體的OS實現時,仍然是需要與OS的圖形系統打交道的。例如,Open GL需要從底層的OS圖形系統中獲得圖形緩沖區來保存渲染結果,并且也需要將渲染好的圖形緩沖區交給底層的OS圖形系統來顯示到設備屏幕去。Open GL與底層的OS圖形系統的這些交互通道都是通過EGL函數來建立的。
至此,將當前窗口綁定到Render Thread的過程就分析完成了,整個Android應用程序UI硬件加速渲染環境的初始化過程也分析完成了。前面在分析ThreadedRenderer對象的創建過程時提到了系統預加載資源地圖集的概念,在繼續分析Android應用程序UI硬件加速渲染的Display List構建和渲染過程之前,我們有必要先分析這個地圖集的概念,因為這是Display List在渲染時涉及到的一個重要優化,敬請關注
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析