原文出處——>[Android應用程序UI硬件加速渲染的動畫執行過程分析](http://blog.csdn.net/luoshengyang/article/details/46449677)
通常我們說一個系統不如另一個系統流暢,說的就是前者動畫顯示不如后者流暢,因此動畫顯示流暢程度是衡量一個系統流暢性的關鍵指標。為什么這樣說呢?這是因為流暢的動畫顯示需要60fps的UI刷新速度,然而這卻不是一個容易達到的速度。Android 5.0通過引入Render Thread盡最大努力提升動畫顯示流暢性。本文就分析Render Thread顯示動畫的過程,以便了解它是如何提高動畫顯示流暢性的。
在前面Android應用程序UI硬件加速渲染技術簡要介紹和學習計劃一文中,我們提到了Render Thread對動畫顯示的兩個優化。第一個優化是在動畫顯示期間,臨時將動畫的目標View的Layer Type設置為LAYER_TYPE_HARDWARE,這樣就可以使得目標View以Open GL里面的Frame Buffer Object(FBO)進行渲染。這種優化的效果就如Render Thread直接以Open GL里面的Texture來渲染TextureView一樣。第二個優化是在Main Thread不需要參與動畫的顯示過程時,動畫就會被注冊到Render Thread中,這樣動畫的計算和顯示過程就完全由Render Thread來負責。這種優化帶來的好處就是在動畫顯示期間,Main Thread可以去處理其它的用戶輸入,而且動畫的顯示也會更加流暢。
上面描述的兩種動畫優化涉及到的Main Thread和Render Thread的交互過程如圖1所示:
:-: 
圖1 Main Thread與Render Thread的動畫交互模型
接下來,我們就通過代碼分析上述的兩種動畫顯示優化過程。
我們通過調用View類的成員函數animate可以獲得一個ViewPropertyAnimator對象,如下所示:
~~~
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
......
public ViewPropertyAnimator animate() {
if (mAnimator == null) {
mAnimator = new ViewPropertyAnimator(this);
}
return mAnimator;
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/View.java中。
有了這個ViewPropertyAnimator對象之后,就可以調用它的成員函數withLayer將它關聯的View的Layer Type設置為LAYER_TYPE_HARDWARE,如下所示:
~~~
public class ViewPropertyAnimator {
......
public ViewPropertyAnimator withLayer() {
mPendingSetupAction= new Runnable() {
@Override
public void run() {
mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (mView.isAttachedToWindow()) {
mView.buildLayer();
}
}
};
final int currentLayerType = mView.getLayerType();
mPendingCleanupAction = new Runnable() {
@Override
public void run() {
mView.setLayerType(currentLayerType, null);
}
};
......
return this;
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewPropertyAnimator.java中。
ViewPropertyAnimator類的成員函數withLayer創建了兩個Runnable,分別保存在成員變量mPendingSetupAction和mPendingCleanupAction中。其中,成員變量mPendingSetupAction指向的Runnable在動畫開始顯示之前執行,而成員變量mPendingCleanupAction指向的Runnable在動畫結束顯示之后執行。由此我們就可以看到:
1. 在動畫開始顯示之前,目標View的Layer Type會被設置為LAYER_TYPE_HARDWARE,并且它的成員函數buildLayer會被調用來創建一個Layer。
2. 在動畫結束顯示之后,目標View的Layer Type會被恢復為它之前的Layer Type。注意,這里調用目標View的成員函數getLayerType獲得的是它的Layer Type未被設置為LAYER_TYPE_HARDWARE的Layer Type。
接下來我們就繼續分析View類的成員函數buildLayer的實現,以便可以了解為一個View設置一個Layer的過程。
View類的成員函數buildLayer的實現如下所示:
~~~
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
......
public void buildLayer() {
......
final AttachInfo attachInfo = mAttachInfo;
......
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
updateDisplayListIfDirty();
if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
}
break;
case LAYER_TYPE_SOFTWARE:
buildDrawingCache(true);
break;
}
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/View.java中。
前面已經將當前正在處理的View的Layer Type設置為LAYER_TYPE_HARDWARE,因此View類的成員函數buildLayer首先是調用我們在前面Android應用程序UI硬件加速渲染的Display List構建過程分析一文中分析過的View類的另外一個成員函數updateDisplayListIfDirty更新它的Display List。更新完畢之后,再調用保存在成員變量mAttachInfo描述的一個AttachInfo對象的成員變量mHardwareRenderer指向的一個ThreadedRenderer對象的成員函數buildLayer為當前正在處理的View創建一個Layer。
從這里還可以看到,如果當前正在處理的View的Layer Type被設置為LAYER_TYPE_SOFTWARE,即該View是以軟件方式進行渲染的,那么就會調用另外一個成員函數buildDrawingCache將View上次繪制得到的UI緩存在一個Bitmap中,以便下次可以快速地繪制View動畫的下一幀。View類的成員函數buildDrawingCache的實現,同樣可以參考前面Android應用程序UI硬件加速渲染的Display List構建過程分析一文。
接下來我們主要關注為一個View創建一個Layer的過程,即ThreadedRenderer對象的成員函數buildLayer的實現,如下所示:
~~~
public class ThreadedRenderer extends HardwareRenderer {
......
@Override
void buildLayer(RenderNode node) {
nBuildLayer(mNativeProxy, node.getNativeDisplayList());
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ThreadedRenderer.java中。
ThreadedRenderer對象的成員函數buildLayer調用另外一個成員函數nBuildLayer為參數node描述的一個Render Node關聯的View創建一個Layer。
ThreadedRenderer對象的成員函數nBuildLayer是一個JNI函數,由Native層的函數android_view_ThreadedRenderer_buildLayer實現,如下所示:
~~~
static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong nodePtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
proxy->buildLayer(node);
}
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
參數proxyPtr描述的是一個RenderProxy對象,這里調用它的成員函數buildLayer為參數nodePtr描述的一個Render Node創建一個Layer。
RenderProxy類的成員函數buildLayer的實現如下所示:
~~~
CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
args->context->buildLayer(args->node);
return NULL;
}
void RenderProxy::buildLayer(RenderNode* node) {
SETUP_TASK(buildLayer);
args->context = mContext;
args->node = node;
postAndWait(task);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/RenderProxy.cpp中。
RenderProxy類的成員函數buildLayer首先是通過宏SETUP_TASK創建一個Task,接下來再調用另外一個成員函數postAndWait將該Task添加到Render Thread的Task Queue去等待執行。最后這個Task由宏CREATE_BRIDGE2聲明的函數buildLayer來執行,主要就是調用參數context描述的一個CanvasContext對象的成員函數buildLayer為參數node描述的一個Render Node創建一個Layer。
CanvasContext類的成員函數buildLayer的實現如下所示:
~~~
void CanvasContext::buildLayer(RenderNode* node) {
......
TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
......
node->prepareTree(info);
......
mCanvas->flushLayerUpdates();
......
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthred/CanvasContext.cpp中。
這里就可以看到CanvasContext類的成員函數buildLayer調用了我們在前面Android應用程序UI硬件加速渲染的Display List渲染過程分析一文的關鍵函數——RenderNode類的成員函數prepareTree,它用來將參數node描述的Render Node的Display List從Main Thread同步到Render Thread中,并且為該Render Node創建了一個Layer,但是這個Layer處理待更新狀態。
CanvasContext類的成員函數buildLayer接下來繼續調用成員變量mCanvas指向的一個OpenGLRenderer對象的成員函數flushLayerUpdates更新剛才創建的Layer,它的實現如下所示:
~~~
void OpenGLRenderer::flushLayerUpdates() {
......
updateLayers();
flushLayers();
......
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/OpenGLRenderer.cpp中。
OpenGLRenderer類的成員函數flushLayerUpdates主要是執行了以下兩個操作:
1. 調用成員函數updateLayers重排和合并所有設置了Layer的Render Node的Display List的繪制命令,這些Layer包括了我們在前面一步創建的Layer。
2. 調用成員函數flushLayers執行所有設置了Layer的經過了重排和合并的Render Node的Display List的繪制命令,使得每一個這樣的Render Node的UI都分別渲染在一個FBO上。
關于OpenGLRenderer類的成員函數updateLayers和flushLayers的實現,可以參考前面Android應用程序UI硬件加速渲染的Display List渲染過程分析一文。
這樣,我們就臨時地為一個即將要顯示動畫的View創建了一個Layer,這個Layer將即將要顯示的動畫的View的UI渲染在一個FBO,這樣以后就可以基于這個FBO來更高效率地顯示動畫了。
后面的動畫顯示過程實質上就不斷地渲染應用程序窗口的UI,這個過程可以參考前面Android應用程序UI硬件加速渲染的Display List渲染過程分析一文。不過,再結合前面Android應用程序UI硬件加速渲染的Display List構建過程分析一文,我們可以知道,在這個過程中,并不是應用程序窗口視圖中的每一個View的Display List都是需要重建的,而且對于要顯示動畫的View,我們也只是需要將動畫參數應用在前面為它創建的FBO之上即可。當然,為了得到應用程序窗口的UI,在渲染的過程中,需要重新執行一遍應用程序窗口視圖中的每一個View的Display List的繪制命令。我們可以將這個過程看作是應用程序窗口的各個View的UI合成過程。相對于應用程序窗口的每一個View的Display List構建,以及對它里面的繪制命令進行重排和合并的過程來說,上述合成過程的成本是低很多的。
以上分析的就是View動畫顯示過程中的第一種優化,即在View的動畫開始顯示之前,臨時地為它創建一個Layer,使得View的UI渲染在一個FBO上,以后的動畫就直接作用在該FBO上。接下來我們繼續分析View動畫顯示過程的第二種優化,即將View動畫的計算和顯示完全交給Render Thread來負責。
當我們通過View類的成員函數animate獲得了一個即將要顯示動畫的View關聯的ViewPropertyAnimator對象之后,就可以通過這個ViewPropertyAnimator對象設置各種動畫參數。動畫參數設置完畢,就可以調用上述ViewPropertyAnimator對象的成員函數start進行動畫顯示。
ViewPropertyAnimator類的成員函數start的實現如下所示:
~~~
public class ViewPropertyAnimator {
......
public void start() {
......
startAnimation();
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewPropertyAnimator.java中。
ViewPropertyAnimator類的成員函數start調用了另外一個成員函數startAnimation來啟動動畫,后者的實現如下所示:
~~~
public class ViewPropertyAnimator {
......
/**
* A RenderThread-driven backend that may intercept startAnimation
*/
private ViewPropertyAnimatorRT mRTBackend;
......
private void startAnimation() {
if (mRTBackend != null && mRTBackend.startAnimation(this)) {
return;
}
......
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
......
animator.start();
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewPropertyAnimator.java中。
ViewPropertyAnimator類的成員函數startAnimation首先是檢查成員變量mRTBackend的值是否等于null。如果不等于null,那么它指向的就是一個ViewPropertyAnimatorRT對象,因此接下來就調用該ViewPropertyAnimatorRT對象的成員函數startAnimation來執行動畫相關的操作。
如果調用ViewPropertyAnimator類的成員變量mRTBackend指向的ViewPropertyAnimatorRT對象的成員函數startAnimation得到的返回值為true,就表示由Render Thread完全負責動畫的計算以及顯示。否則的話,就需要由Main Thread負責動畫的計算,然后將計算好的動畫應用在View上,再由Render Thread負責將動畫顯示出來。
從ViewPropertyAnimator類的成員變量mRTBackend的注釋我們也可以看到,ViewPropertyAnimatorRT類是用來攔截ViewPropertyAnimator類負責的動畫的,也就是將動畫完全交給Render Thread來管理。不過在5.0的代碼中,還沒有看到任何初始化ViewPropertyAnimator類的成員變量mRTBackend的代碼。這就是意味著ViewPropertyAnimator類的成員變量mRTBackend始終為null,因此就不會去調用ViewPropertyAnimatorRT類的成員函數startAnimation。
我們相信以后ViewPropertyAnimatorRT類的功能一定會派上用場的,因此接下來我們就假設ViewPropertyAnimator類的成員變量mRTBackend已經被始化,這樣我們就可以更好地理解我們上面提到的動畫顯示的第二種優化。
ViewPropertyAnimatorRT類的成員函數startAnimation的實現如下所示:
~~~
class ViewPropertyAnimatorRT {
......
public boolean startAnimation(ViewPropertyAnimator parent) {
......
if (!canHandleAnimator(parent)) {
return false;
}
doStartAnimation(parent);
return true;
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewPropertyAnimatorRT.java中。
ViewPropertyAnimatorRT類的成員函數startAnimation首先是調用成員函數canHandleAnimator判斷是否能夠讓Render Thread來完全負責當前正在處理的動畫。如果不能完全負責,那么就返回一個false值給調用者。否則的話,就調用另外一個成員函數doStartAnimation將當前正在處理的動畫交給Render Thread來管理。
我們先看什么情況下ViewPropertyAnimatorRT類的成員函數startAnimation不能讓Render Thread來完全負責當前正在處理的動畫,也就是ViewPropertyAnimatorRT類的成員函數canHandleAnimator的實現,如下所示:
~~~
class ViewPropertyAnimatorRT {
......
private boolean canHandleAnimator(ViewPropertyAnimator parent) {
......
if (parent.getUpdateListener() != null) {
return false;
}
if (parent.getListener() != null) {
// TODO support
return false;
}
if (!mView.isHardwareAccelerated()) {
// TODO handle this maybe?
return false;
}
if (parent.hasActions()) {
return false;
}
// Here goes nothing...
return true;
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewPropertyAnimatorRT.java中。
參數parent指向的是一個ViewPropertyAniamtor對象,該ViewPropertyAniamtor對象原先是由它負責顯示View的動畫的,現在ViewPropertyAnimatorRT類的成員函數canHandleAnimator判斷它是否設置了一系列的Listener。如果設置了,就意味著Main Thread需要獲得動畫顯示過程中的通知,這樣就不能將一個動畫完全地將交給Render Thread來管理。
上面提到的Listener有兩個:
1. 用來監聽動畫更新事件的Listener。這個Listener如果設置有,那么就可以通過調用ViewPropertyAniamtor類的成員函數getUpdateListener獲得。
2. 用來監聽動畫的開始和結束等事件的Listener。這個Listener如果設置有,那么就可以通過調用ViewPropertyAniamtor類的成員函數getListener獲得。
此外,如我們前面所述,如果在View的動畫顯示之前,我們調用了與它關聯的ViewPropertyAniamtor對象的成員函數withLayer,那么與它關聯的ViewPropertyAniamtor對象就會在內部創建兩個Runnable。這兩個Runnable用來臨時地將要顯示動畫的View的Layer Type設置為LAYER_TYPE_HARDWARE。在這種情況下,調用與View關聯的ViewPropertyAniamtor對象的成員函數hasActions得到的返回值就等于true。這意味著Main Thread需要獲得動畫顯示開始和結束的通知,因此就不能將一個動畫完全地將交給Render Thread來管理。
再者,如果要顯示動畫的View不支持硬件加速渲染,即調用它的成員函數isHardwareAccelerated得到的返回值等于false。很明顯,Render Thread是通過硬件加速渲染的方式來顯示View的動畫的。因此,在這種情況下,也不能將一個動畫完全地交給Render Thread來管理。
我們假設ViewPropertyAnimatorRT類的成員函數canHandleAnimator的返回值為true,那么接下來就會調用到ViewPropertyAnimatorRT類的成員函數doStartAnimation,它的實現如下所示:
~~~
class ViewPropertyAnimatorRT {
......
private void doStartAnimation(ViewPropertyAnimator parent) {
int size = parent.mPendingAnimations.size();
......
for (int i = 0; i < size; i++) {
NameValuesHolder holder = parent.mPendingAnimations.get(i);
int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
final float finalValue = holder.mFromValue + holder.mDeltaValue;
RenderNodeAnimator animator = new RenderNodeAnimator(property, finalValue);
animator.setStartDelay(startDelay);
animator.setDuration(duration);
animator.setInterpolator(interpolator);
animator.setTarget(mView);
animator.start();
mAnimators[property] = animator;
}
parent.mPendingAnimations.clear();
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewPropertyAnimatorRT.java中。
當前要顯示的動畫保存在參數parent描述的一個ViewPropertyAnimator對象的成員變量mPendingAnimations描述的一個NameValuesHodler對象列表中。ViewPropertyAnimatorRT類的成員函數doStartAnimation為這個列表的每一個NameValuesHodler對象都創建一個RenderNodeAnimator對象,并且將相關的動畫參數都設置到新創建的RenderNodeAnimator對象中去。當這些參數設置完畢,就可以調用新創建的RenderNodeAnimator對象的成員函數start,來它們標記為可以執行的狀態。
其中,上述新創建的RenderNodeAnimator對象有一個重要的參數需要設置,就是它所關聯的View,這是通過調用RenderNodeAnimator類的成員函數setTarget來完成的。RenderNodeAnimator類的成員函數setTarget在執行的過程中,就會將相關的動畫注冊到Render Thread中去,以便Render Thread可以執行它們。
RenderNodeAnimator類的成員函數setTarget的實現如下所示:
~~~
public class RenderNodeAnimator extends Animator {
......
public void setTarget(View view) {
mViewTarget = view;
setTarget(mViewTarget.mRenderNode);
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/RenderNodeAnimator.java中。
參數view描述的就是要顯示動畫的View,RenderNodeAnimator類的成員函數setTarget首先是將它保存成員變量mTargetView中,接著再獲得與它關聯的一個Render Node傳遞給另外一個重載版本的成員函數setTarget處理,如下所示:
~~~
public class RenderNodeAnimator extends Animator {
......
private void setTarget(RenderNode node) {
......
mTarget = node;
mTarget.addAnimator(this);
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/RenderNodeAnimator.java中。
RenderNodeAnimator類的重載版本的成員函數setTarget首先是將參數node描述的一個Render Node保存在成員變量mTarget中,接著再通過調用RenderNode類的成員函數addAniamtor將當前正在處理的動畫注冊到Render Thread中去。
RenderNode類的成員函數addAniamtor的實現如下所示:
~~~
public class RenderNode {
......
public void addAnimator(RenderNodeAnimator animator) {
......
nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/RenderNode.java中。
RenderNode類的成員函數addAniamtor首先是調用另外一個成員函數nAddAnimator將參數animator描述的動畫注冊到Render Thread中去。
RenderNode類的成員變量mOwningView描述的是一個與當前正在處理的Render Node關聯的一個View,這個View就是要顯示動畫的View。每一個View都有一個成員變量mAttachInfo,它指向的是一個AttachInfo對象,該AttachInfo對象描述的是一個View所屬的窗口的相關信息。其中,這個AttachInfo對象有一個成員變量mViewRootImpl,它指向的是一個ViewRootImpl對象,該ViewRootImpl對象負責管理一個View所屬的窗口,例如用來分發輸入事件給窗口,以及用來發起窗口的繪制流程等。
RenderNode類的成員函數addAniamtor接下來要做的事情就是調用上述的ViewRootImpl對象的成員函數registerAnimatingRenderNode告訴Render Thread,當前正在處理的Render Node有動畫注冊到了它里面,這樣Render Node就可以將渲染應用窗口的下一幀時,顯示前面已經注冊的動畫。
接下來我們就先分析RenderNode類的成員函數nAddAnimator的實現,接著再分析ViewRootImpl類的成員函數registerAnimatingRenderNode的實現。
RenderNode類的成員函數nAddAnimator是一個JNI函數,由Native層的函數android_view_RenderNode_addAnimator實現,如下所示:
~~~
static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz,
jlong renderNodePtr, jlong animatorPtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
renderNode->addAnimator(animator);
}
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_RenderNode.cpp中。
參數renderNodePtr指向的是Native層的一個RenderNode對象,該RenderNode對象與要顯示動畫的View關聯。參數animatorPtr指向的Native層的一個RenderPropertyAnimator對象,該RenderPropertyAnimator對象描述的就是要顯示的動畫。這里調用RenderNode類的成員函數addAnimator將參數animatorPtr描述的動畫保存在參數renderNodePtr描述的Render Node的內部。
RenderNode類的成員函數addAnimator的實現如下所示:
~~~
void RenderNode::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mAnimatorManager.addAnimator(animator);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/RenderNode.cpp中。
RenderNode類的成員變量mAnimatorManager描述的是一個AnimatorManager對象。這個AnimatorManager對象用來管理一個RenderNode對象所關聯的動畫。因此,RenderNode類的成員函數addAnimator所做的事情就是將參數animator描述的動畫保存在當前正在處理的RenderNode對象內部的一個AnimatorManager對象中,這是通過調用AnimatorManager類的成員函數addAnimator完成的。
AnimatorManager類的成員函數addAnimator的實現如下所示:
~~~
void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
animator->incStrong(0);
animator->attach(&mParent);
mNewAnimators.push_back(animator.get());
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimatorMaager.cpp中。
在分析AnimatorManager類的成員函數addAnimator的實現之前,我們首先了解AnimatorManager類的三個成員變量:
1. mParent,它描述的是一個RenderNode對象,該RenderNode對象與當前正在處理的AnimatorManager對象關聯。
2. mNewAnimators,它描述的是一個Vector,該Vector用來保存新增加的動畫。
3. mAnimators,它描述的也是一個Vector。在繪制應用程序窗口的下一幀之前,新增加的動畫會從成員變量mNewAnimators描述的Vector轉移到成員變量mAnimators描述的Vector中去等待處理。
AnimatorManager類的成員函數addAnimator首先是增加參數animator描述的一個BaseRenderNodeAnimator對象的引用計數,因為后面要將它添加成員變量mNewAnimators描述的一個Vector中去。此外,AnimatorManager類的成員函數addAnimator還會調用參數animator描述的一個BaseRenderNodeAnimator對象的成員函數attach將該BaseRenderNodeAnimator對象與要顯示動畫的Render Node進行關聯。
這一步執行完成之后,我們就將要顯示的動畫設置到目標View關聯的一個RenderNode對象內部的一個AnimatorManager對象中去了。返回到Java層的RenderNode類的成員函數addAniamtor中,接下來我們繼續分析ViewRootImpl類的成員函數registerAnimatingRenderNode的實現,以便可以了解Render Thread知道有Render Node有新的動畫需要顯示的過程。
ViewRootImpl類的成員函數registerAnimatingRenderNode的實現如下所示:
~~~
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
public void registerAnimatingRenderNode(RenderNode animator) {
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.registerAnimatingRenderNode(animator);
} else {
if (mAttachInfo.mPendingAnimatingRenderNodes == null) {
mAttachInfo.mPendingAnimatingRenderNodes = new ArrayList<RenderNode>();
}
mAttachInfo.mPendingAnimatingRenderNodes.add(animator);
}
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ViewRootImpl.java中。
當ViewRootImpl類的成員變量mAttachInfo指向的一個AttachInfo對象的成員變量mHardwareRenderer的值不等于null的時候,它指向的是一個ThreadedRenderer對象。在這種情況下,ViewRootImpl類的成員函數registerAnimatingRenderNode會直接調用該ThreadedRenderer對象的成員函數registerAnimatingRenderNode將參數animator描述的一個Render Node注冊到Render Thread中去,以便Render Thread知道哪些Render Node有新的動畫需要顯示。
另一方面,當ViewRootImpl類的成員變量mAttachInfo指向的一個AttachInfo對象的成員變量mHardwareRenderer的值等于null的時候,這意味著應用程序窗口使用軟件渲染或者使用硬件加速渲染但是硬件加速渲染環境還沒有初始化好。在這兩種情況下,都是先將參數animator描述的Render Node保存在成員變量mAttachInfo指向的一個AttachInfo對象的成員變量mPendingAnimatingRenderNodes描述的一個列表中等待處理。
從前面Android應用程序UI硬件加速渲染的Display List構建過程分析一文可以知道,當使用硬件加速渲染時,應用程序窗口的渲染是從調用ThreadedRenderer類的成員函數draw開始的,它的實現如下所示:
~~~
public class ThreadedRenderer extends HardwareRenderer {
......
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
......
updateRootDisplayList(view, callbacks);
......
if (attachInfo.mPendingAnimatingRenderNodes != null) {
final int count = attachInfo.mPendingAnimatingRenderNodes.size();
for (int i = 0; i < count; i++) {
registerAnimatingRenderNode(
attachInfo.mPendingAnimatingRenderNodes.get(i));
}
attachInfo.mPendingAnimatingRenderNodes.clear();
// We don't need this anymore as subsequent calls to
// ViewRootImpl#attachRenderNodeAnimator will go directly to us.
attachInfo.mPendingAnimatingRenderNodes = null;
}
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
recordDuration, view.getResources().getDisplayMetrics().density);
if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
attachInfo.mViewRootImpl.invalidate();
}
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ThreadedRenderer.java中。
ThreadedRenderer類的成員函數draw在調用成員函數updateRootDisplayList構建應用程序窗口的Display List之后,并且調用成員函數nSyncAndDrawFrame渲染應用程序窗口的Display List之前,會調用成員函數registerAnimatingRenderNode處理保存在上面提到的AttachInfo對象的成員變量mPendingAnimatingRenderNodes描述的一個列表中的每一個Render Node。
ThreadedRenderer類的成員函數registerAnimatingRenderNode的實現如下所示:
~~~
public class ThreadedRenderer extends HardwareRenderer {
......
@Override
void registerAnimatingRenderNode(RenderNode animator) {
nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/view/ThreadedRenderer.java中。
ThreadedRenderer類的成員函數registerAnimatingRenderNode調用另外一個成員函數nRegisterAnimatingRenderNode將參數animator描述的一個Render Node注冊到Render Thread中去。
ThreadedRenderer類的成員函數nRegisterAnimatingRenderNode是一個JNI函數,由Native層的函數android_view_ThreadedRenderer_registerAnimatingRenderNode實現,如下所示:
~~~
static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
jlong rootNodePtr, jlong animatingNodePtr) {
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
rootRenderNode->attachAnimatingNode(animatingNode);
}
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
參數rootNodePtr指向的是一個RootRenderNode對象,該RootRenderNode對象描述的是應用程序窗口的Root Render Node,這里主要就是將參數animatorNodePtr描述的一個Render Node注冊在上述的RootRenderNode對象的內部,這是通過調用RootRenderNode類的成員函數attachAnimatingNode實現的。
RootRenderNode類的成員函數attachAnimatingNode的實現如下所示:
~~~
class RootRenderNode : public RenderNode, ErrorHandler {
public:
......
void attachAnimatingNode(RenderNode* animatingNode) {
mPendingAnimatingRenderNodes.push_back(animatingNode);
}
......
private:
......
std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
};
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
RootRenderNode類的成員函數attachAnimatingNode將參數animatingNode描述的一個Render Node保存成員變量mPendingAnimatingRenderNodes描述的一個Vector中。保在這個Vector中的Render Node將會在應用程序窗口的下一幀被渲染時得到處理。
從前面Android應用程序UI硬件加速渲染的Display List渲染過程分析一文可以知道,Render Thread在渲染應用程序窗口的下一幀時,會調用CanvasContext類的成員函數prepareTree將應用程序窗口的Display List從Main Thread同步到Render Thread,如下所示:
~~~
void CanvasContext::prepareTree(TreeInfo& info) {
......
info.renderer = mCanvas;
......
mAnimationContext->startFrame(info.mode);
mRootRenderNode->prepareTree(info);
mAnimationContext->runRemainingAnimations(info);
......
int runningBehind = 0;
// TODO: This query is moderately expensive, investigate adding some sort
// of fast-path based off when we last called eglSwapBuffers() as well as
// last vsync time. Or something.
mNativeWindow->query(mNativeWindow.get(),
NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
info.out.canDrawThisFrame = !runningBehind;
if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
if (!info.out.requiresUiRedraw) {
// If animationsNeedsRedraw is set don't bother posting for an RT anim
// as we will just end up fighting the UI thread.
mRenderThread.postFrameCallback(this);
}
}
}
~~~
這個函數定義定義在文件frameworks/base/libs/hwui/renderthread/CanvasContext.cpp中。
CanvasContext類的成員函數prepareTree的詳細實現分析可以參考前面Android應用程序UI硬件加速渲染的Display List渲染過程分析一文,這里我們主要關注與動畫相關的兩個操作:
1. 第一個操作是在調用RenderNode類的成員函數prepareTree同步應用程序窗口的Display List之前,調用成員變量mAnimationContext描述的一個AnimationContext對象的成員函數startFrame執行一些動畫顯示的準備工作。
2. 第二個操作是在調用RenderNode類的成員函數prepareTree同步應用程序窗口的Display List之后,調用成員變量mAnimationContext描述的一個AnimationContext對象的成員函數runRemainingAnimations更新剩下的還未完成的動畫。
接下來我們就分別分析這兩個操作的執行過程,即分析AnimationContext類的成員函數startFrame和runRemainingAnimations的實現。不過,在分析這兩個函數的實現之前,我們首先要了解CanvasContext類的成員變量mAnimationContext的初始化過程。
從前面Android應用程序UI硬件加速渲染環境初始化過程分析一文可以知道,在Android應用程序的硬件加速渲染環境的初始化過程中,會創建一個RenderProxy對象,如下所示:
~~~
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中。
在調用RenderProxy類的構造函數創建一個RenderProxy對象的時候,傳遞進去的第三個參數是一個ContextFactoryImpl對象。
我們繼續看RenderProxy類的構造函數的實現,如下所示:
~~~
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)
: 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類的構造函數首先是向Render Thread的Task Queue發送一個Task,并且等待該Task執行完成。上述Task在執行的時候,會調用由宏CREATE_BRIDGE4聲明的函數createContext。該函數所做的事情就是創建一個CanvasContext對象。該CanvasContext對象最終保存在RenderProxy類的成員變量mContext中。
在調用CanvasContext類的構造函數創建一個CanvasContext對象的時候,傳遞進去的第四個參數就是在前面分析的函數android_view_ThreadedRenderer_createProxy聲明的一個ContextFactoryImpl對象。
CanvasContext類的構造函數的實現如下所示:
~~~
CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory)
:...... {
mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord());
......
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/renderthread/CanvasContext.cpp中。
從這里就可以看出,CanvasContext的成員變量mAnimationContext指向的一個AnimationContext對象是由參數contextFactory描述的一個IContextFactory接口的成員函數createAnimationContext創建的。
從前面的調用過程可以知道,參數contextFactory指向的實際上是一個ContextFactoryImpl對象,它的成員函數createAnimationContext的實現如下所示:
~~~
class ContextFactoryImpl : public IContextFactory {
public:
ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
return new AnimationContextBridge(clock, mRootNode);
}
private:
RootRenderNode* mRootNode;
};
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
ContextFactoryImpl類的成員函數createAnimationContext創建的是一個AnimationContextBridge對象,由此就可見,CanvasContext的成員變量mAnimationContext實際指向的一個AnimationContextBridge對象。
明白了這一點之后,回到前面分析的CanvasContext類的成員函數prepareTree中,它在同步應用程序窗口的Display List之前,調用了AnimationContextBridge類的成員函數startFrame執行一些動畫顯示的準備工作。
AnimationContextBridge類的成員函數startFrame的實現如下所示:
~~~
class AnimationContextBridge : public AnimationContext {
public:
......
// Marks the start of a frame, which will update the frame time and move all
// next frame animations into the current frame
virtual void startFrame(TreeInfo::TraversalMode mode) {
if (mode == TreeInfo::MODE_FULL) {
mRootNode->doAttachAnimatingNodes(this);
}
AnimationContext::startFrame(mode);
}
......
private:
sp<RootRenderNode> mRootNode;
......
};
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
參數mode的值等于TreeInfo::MODE_FULL,表示目前Render Thread是處于同步應用程序窗口的Display List的過程中。在這種情況下,AnimationContextBridge類的成員函數startFrame執行兩個操作:
1. 調用成員變量mRootNode描述的一個RootRenderNode對象的成員函數doAttachAnimatingNodes處理它內部保存的有動畫顯示的Render Node。
2. 調用父類AnimationContext的成員函數startFrame繼續執行一些動畫顯示之前的準備工作。
接下來,我們就先分析RootRenderNode類的成員函數doAttachAnimatingNodes的實現,再分析AnimationContext類的成員函數startFrame的實現。
RootRenderNode類的成員函數doAttachAnimatingNodes的實現如下所示:
~~~
class RootRenderNode : public RenderNode, ErrorHandler {
public:
......
void doAttachAnimatingNodes(AnimationContext* context) {
for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
RenderNode* node = mPendingAnimatingRenderNodes[i].get();
context->addAnimatingRenderNode(*node);
}
mPendingAnimatingRenderNodes.clear();
}
private:
......
std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
};
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
RootRenderNode類的成員函數doAttachAnimatingNodes遍歷保存在成員變量mPendingAnimatingRenderNodes描述的一個Vector中的每一個RenderNode對象,并且分別調用參數context描述的一個AnimationContextBridge對象的成員函數addAnimatingRenderNode對它們進行處理。
AnimationContextBridge類的成員函數addAnimatingRenderNode是從父類AnimationContext繼承下來的,它的實現如下所示:
~~~
void AnimationContext::addAnimatingRenderNode(RenderNode& node) {
if (!node.animators().hasAnimationHandle()) {
AnimationHandle* handle = new AnimationHandle(node, *this);
addAnimationHandle(handle);
}
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimationContext.cpp中。
參數node指向的是一個RenderNode對象,調用它的成員函數animators可以獲得它內部的一個AnimatorManager對象。如果該AnimatorManager對象還沒有設置過一個AnimationHandle對象,那么AnimationContext類的成員函數addAnimatingRenderNode就為其設置一個AnimationHandle對象,并且這個AnimationHandle對象會通過AnimationContext類的成員函數addAnimationHandle保存在當前正在處理的一個AnimationContext對象的內部。
AnimationContext類的成員函數addAnimationHandle的實現如下所示:
~~~
void AnimationContext::addAnimationHandle(AnimationHandle* handle) {
handle->insertAfter(&mNextFrameAnimations);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimationContext.cpp中。
AnimationContext類的成員函數addAnimationHandle所做的事情就是將參數handle描述的一個AnimationHandle對象插入成員變量mNextFrameAnimations描述的一個AnimationHandle列表中。
由此我們就可以推斷出,只要AnimationContext類的成員變量NextFrameAnimations描述的一個AnimationHandle列表不為空,那么就意味著Render Thread在渲染應用程序窗口的下一幀的時候,有Render Node需要顯示動畫。
這一步執先完成之后,返回到AnimationContextBridge類的成員函數startFrame中,接下來它所做的事情就是調用父類AnimationContext的成員函數startFrame繼續執行一些動畫顯示之前的準備工作。
AnimationContext的成員函數startFrame的實現如下所示:
~~~
void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
......
AnimationHandle* head = mNextFrameAnimations.mNextHandle;
if (head) {
mNextFrameAnimations.mNextHandle = NULL;
mCurrentFrameAnimations.mNextHandle = head;
head->mPreviousHandle = &mCurrentFrameAnimations;
}
......
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimationContext.cpp中。
AnimationContext的成員函數startFrame所做的事情就是將成員變量mNextFrameAnimations描述的一個AnimationHandle列表轉移到另外一個成員變量mCurrentFrameAnimations中。
由此我們就可以推斷出,只要AnimationContext類的成員變量mCurrentFrameAnimations描述的一個AnimationHandle列表不為空,那么就意味著Render Thread在渲染應用程序窗口的當前幀的時候,有Render Node需要顯示動畫。
這一步執行完成之后,返回到CanvasContext類的成員函數prepareTree中,當它同步同步應用程序窗口的Display List之后,就調用成員變量mAnimationContext描述的一個AnimationContextBridge對象的成員函數runRemainingAnimations更新剩下的還未完成的動畫。
AnimationContextBridge類的成員函數runRemainingAnimations的實現如下所示:
~~~
class AnimationContextBridge : public AnimationContext {
public:
......
// Runs any animations still left in mCurrentFrameAnimations
virtual void runRemainingAnimations(TreeInfo& info) {
AnimationContext::runRemainingAnimations(info);
......
}
......
};
~~~
這個函數定義在文件frameworks/base/core/jni/android_view_ThreadedRenderer.cpp中。
AnimationContextBridge類的成員函數runRemainingAnimations主要是通過調用父類AnimationContext的成員函數runRemainingAnimations更新剩下的還未完成的動畫。
AnimationContext類的成員函數runRemainingAnimations的實現如下所示:
~~~
void AnimationContext::runRemainingAnimations(TreeInfo& info) {
while (mCurrentFrameAnimations.mNextHandle) {
AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
AnimatorManager& animators = current->mRenderNode->animators();
animators.pushStaging();
animators.animateNoDamage(info);
......
}
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimationContext.cpp中。
前面提到,應用程序窗口當前幀要顯示動畫都記錄在AnimationContext類的成員mCurrentFrameAnimations描述的一個AnimationHandle列表中。因此,AnimationContext類的成員函數runRemainingAnimations就遍歷這個列表中的每一個AnimationHandle,并且獲得與其關聯的一個AnimatorManager。有了這些AnimatorManager之的,就可以調用它們的成員函數pushStaging和animateNoDamage來執行動畫,其實就是計算動畫的下一幀參數,以便應用在目標Render Node上。
AnimatorManager類的成員函數pushStaging的實現如下所示:
~~~
void AnimatorManager::pushStaging() {
if (mNewAnimators.size()) {
......
move_all(mNewAnimators, mAnimators);
}
for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
(*it)->pushStaging(mAnimationHandle->context());
}
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimatorManager.cpp中。
從前面的分析可以知道,一開始的時候,應用程序窗口新增加的動畫都保存在AnimatorManager類的成員變量mNewAnimators描述的一個Vector中,這里將它們移動至AnimatorManager類的另外一個成員變量mAnimators中,類似于我們在前面Android應用程序UI硬件加速渲染的Display List渲染過程分析一文提到的將Display List從Main Thread同步到Render Thread一樣。
最后,AnimatorManager類的成員函數pushStaging遍歷已經移動至新列表中的每一個動畫,并且調用它們的成員函數pushStaging,用來同步它們的開始和結束狀態,也就是檢查動畫是否已經被start或者已經end了。如果已經被start,那么就執行一些動畫開始執行前的準備工作,例如計算動畫的開始時間。如果已經end,就發出事件通知給偵聽者。
這一步執行完成之后,回到前面分析的AnimationContext類的成員函數runRemainingAnimations中,接下來就調用AniamtorManager類的成員函數animateNoDamage執行動畫,它的實現如下所示:
~~~
void AnimatorManager::animateNoDamage(TreeInfo& info) {
if (!mAnimators.size()) return;
animateCommon(info);
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimatorManager.cpp中。
AniamtorManager類的成員函數animateNoDamage通過調用另外一個成員函數animateCommon來執行當前正在處理的AnimatorManager對象關聯的動畫,也就是某一個Render Node關聯的動畫。
AniamtorManager類的成員函數animateCommon的實現如下所示:
~~~
uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
AnimateFunctor functor(info, mAnimationHandle->context());
std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mAnimationHandle->notifyAnimationsRan();
return functor.dirtyMask;
}
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimatorManager.cpp中。
前面提到,當前正在處理的AnimatorManager對象關聯的動畫都保存其成員變量mAnimators描述的一個Vector,因此這里就會通過函數std::remove_if來遍歷這些動畫,并且對于每一個動畫,都通過本地變量functor描述的一個AnimatorFunctor對象的操作符重載函數()來執行它的當前幀。
AnimatorFunctor類的操作符重載函數()執行完成動畫的當前幀之后,如果動畫已經完成,即沒有下一幀了,那么它就會返回一個true值給調用者,這樣會導致函數std::remove_if將該動畫移動至列表的末尾位置。
AnimatorFunctor類的操作符重載函數()的實現如下所示:
~~~
class AnimateFunctor {
public:
AnimateFunctor(TreeInfo& info, AnimationContext& context)
: dirtyMask(0), mInfo(info), mContext(context) {}
bool operator() (BaseRenderNodeAnimator* animator) {
dirtyMask |= animator->dirtyMask();
bool remove = animator->animate(mContext);
if (remove) {
animator->decStrong(0);
} else {
if (animator->isRunning()) {
mInfo.out.hasAnimations = true;
}
if (CC_UNLIKELY(!animator->mayRunAsync())) {
mInfo.out.requiresUiRedraw = true;
}
}
return remove;
}
uint32_t dirtyMask;
private:
TreeInfo& mInfo;
AnimationContext& mContext;
};
~~~
這個函數定義在文件frameworks/base/libs/hwui/AnimatorManager.cpp中。
AnimatorFunctor類的操作符重載函數()主要就是調用參數animator指向的一個BaseRenderNodeAnimator對象的成員函數animate來執行該BaseRenderNodeAnimator對象所描述的動畫的當前幀。
當BaseRenderNodeAnimator類的成員函數animate的返回值等于true的時候,就表示參數animator描述的動畫已經顯示結束了,這意味著它可以從我們上面
- 前言
- 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)的過程分析