1. 程式人生 > >深入理解 Android 卷I

深入理解 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顯示了這二脈的關係:

image

圖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所示:

image

圖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(深入理解AndroidI)的讀書筆記

一:概述 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

深入理解AndroidIII 第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是不公開的,