android系統(tǒng)framework層代碼分析_第1頁
android系統(tǒng)framework層代碼分析_第2頁
android系統(tǒng)framework層代碼分析_第3頁
android系統(tǒng)framework層代碼分析_第4頁
android系統(tǒng)framework層代碼分析_第5頁
已閱讀5頁,還剩34頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

會(huì)計(jì)學(xué)1android系統(tǒng)framework層代碼分析大綱(接上)六Surface系統(tǒng)重難點(diǎn)分析

6.1來之不易的Activity 6.2乾坤大挪移——如何與SurfaceFlinger建立聯(lián)系?

6.3生產(chǎn)者和消費(fèi)者之間的紐帶

6.4SurfaceFlinger的工作流程分析

6.5Transaction分析

6.6CameraService中的嚴(yán)重bug 6.7PageFlip過程分析

第2頁/共39頁第1頁/共39頁一JNI重難點(diǎn)分析1JNI是什么?JavaNativeInterface2JNI在程序中有什么作用?白話:

Java代碼通過JNI調(diào)用Native(C/C++)寫的函數(shù)

Native(C/C++)的函數(shù)操作Java層的函數(shù)(調(diào)用函數(shù)或者操作對象)第3頁/共39頁第2頁/共39頁1.1注冊方法的選擇

什么是注冊?Java中定義的native函數(shù)如何找到Native層對應(yīng)的函數(shù)?如何關(guān)聯(lián)這兩個(gè)函數(shù)?第4頁/共39頁第3頁/共39頁兩種方法:

1靜態(tài)法

2動(dòng)態(tài)法靜態(tài)法:很簡單,就是找根據(jù)一定的函數(shù)命名規(guī)則,在so庫中搜索對應(yīng)的函數(shù)。native_initJava_android_media_MediaScanner_native_1init靜態(tài)法標(biāo)準(zhǔn)步驟:先編寫Java代碼,然后編譯生成.class文件使用Java的工具程序javah,如javah–ooutputpackagename.classname,這樣它會(huì)生成一個(gè)叫output.h的JNI層頭文件。其中packagename.classname是Java代碼編譯后的class文件,而在生成的output.h文件里,聲明了對應(yīng)的JNI層函數(shù),只要實(shí)現(xiàn)里面的函數(shù)即可。第5頁/共39頁第4頁/共39頁靜態(tài)方法工作原理探析及其弊端工作原理當(dāng)Java層調(diào)用native_init函數(shù)時(shí),它會(huì)從對應(yīng)的JNI庫Java_android_media_MediaScanner_native_linit,如果沒有,就會(huì)報(bào)錯(cuò)。如果找到,則會(huì)為這個(gè)native_init和Java_android_media_MediaScanner_native_linit建立一個(gè)關(guān)聯(lián)關(guān)系,其實(shí)就是保存JNI層函數(shù)的函數(shù)指針。以后再調(diào)用native_init函數(shù)時(shí),直接使用這個(gè)函數(shù)指針就可以了。弊端:需要編譯所有聲明了native函數(shù)的類。只有生成了.class文件后,才能交由javah工具。默認(rèn)的Native函數(shù)名字巨長第一次調(diào)用某個(gè)native函數(shù)的時(shí)候,需要搜索so庫中對應(yīng)的Native函數(shù)。(估計(jì)是用dlsym來獲得Native函數(shù)的函數(shù)指針吧?。┑?頁/共39頁第5頁/共39頁動(dòng)態(tài)方法

親,您們從前面靜態(tài)方法的介紹中看到了什么?native函數(shù)和JNI層的函數(shù),不就是找一函數(shù)指針嘛?“不找貴的,只找對的”關(guān)鍵數(shù)據(jù)結(jié)構(gòu):JNINativeMethod如何注冊?第7頁/共39頁第6頁/共39頁QuickQuestion:1什么時(shí)候,在哪兒注冊JNINativeMethod數(shù)組?Answer:在一個(gè)特殊的native函數(shù)中Quesiton:這個(gè)特殊的native函數(shù)又是在什么時(shí)候,在哪兒注冊的?Answer:雞生蛋?蛋生雞?當(dāng)Java層通過System.loadLibrary加載完JNI動(dòng)態(tài)庫后,緊接著會(huì)查找該庫中一個(gè)叫JNI_OnLoad的函數(shù),如果有,就調(diào)用它,而動(dòng)態(tài)注冊的工作就是在這里完成的。

第8頁/共39頁第7頁/共39頁1.2垃圾回收例子:可以在別的函數(shù)使用這個(gè)save_thiz嗎?引用計(jì)數(shù)的作用呢?JNI提供三種類型的引用,足夠滿足親們的需求了!第9頁/共39頁第8頁/共39頁LocalReference:本地引用。在JNI層函數(shù)中使用的非全局引用對象都是LocalReference。它包括函數(shù)調(diào)用時(shí)傳入的jobject、在JNI層函數(shù)中創(chuàng)建的jobject。LocalReference最大的特點(diǎn)就是,一旦JNI層函數(shù)返回,這些jobject就可能被垃圾回收。GlobalReference:全局引用,這種對象如不主動(dòng)釋放,就永遠(yuǎn)不會(huì)被垃圾回收。

WeakGlobalReference:弱全局引用,一種特殊的GlobalReference。在運(yùn)行過程中可能會(huì)被垃圾回收。所以在程序中使用它之前,需要調(diào)用JNIEnv的IsSameObject判斷它是不是被回收了。

第10頁/共39頁第9頁/共39頁調(diào)用NewStringUTF創(chuàng)建一個(gè)jstring對象,它是LocalReference類型。

有可能內(nèi)存不夠用……強(qiáng)烈建議,及時(shí)回收LocalRef……mEnv->DeleteLocalRef(pathStr);

Soeasy?

NotReally!第11頁/共39頁第10頁/共39頁JNI最好的參考資料,一切盡在不言中….

《JavaNativeInterfaceSpecification》從網(wǎng)上下載PDFJDK文檔中也有(可下載chm版的,查詢方便……)第12頁/共39頁第11頁/共39頁二init重難點(diǎn)分析Android對init進(jìn)行了大規(guī)模改進(jìn)……,但還是少不了要解析配置文件init.rc。所以,init的破解關(guān)鍵在init.rc的解析代碼中,解析功能在parser.c第13頁/共39頁第12頁/共39頁2.1keywords.h的用法聲明一些Action函數(shù)定義KEYWORD宏,四個(gè)參數(shù),卻只用到第一個(gè)參數(shù)使用KEYWORD宏,得到一個(gè)枚舉:enum{K_UNKNOWN,K_class,K_on……}第14頁/共39頁第13頁/共39頁兩次includekeywords.hInteresting

:includekeywords.htwotimes?Whatdoweget?第一次包含:得到枚舉定義和一些函數(shù)重新定義KEYWROD宏四個(gè)參數(shù)全用上了定義一個(gè)結(jié)構(gòu)體數(shù)組keyword_info再次包含keywords.h實(shí)際上是以枚舉定義的元素為數(shù)組索引,填充keyword_info數(shù)組(用新的KEYWORD宏)第15頁/共39頁第14頁/共39頁Result:明白了?奇技淫巧乎?第16頁/共39頁第15頁/共39頁2.2用好“DllMain函數(shù)”——客戶端Property讀取的實(shí)現(xiàn)Android平臺提供系統(tǒng)級別的屬性管理和控制類比Windows平臺上的“注冊表”:可以存儲一些類似key/value的鍵值對。作用:一般而言,系統(tǒng)或某些應(yīng)用程序會(huì)把自己的一些屬性存儲在注冊表中,即使下次系統(tǒng)重啟或應(yīng)用程序重啟,它還能夠根據(jù)之前在注冊表中設(shè)置的屬性,進(jìn)行相應(yīng)的初始化工作。第17頁/共39頁第16頁/共39頁Diveintocode這個(gè)變量由bioniclibc庫輸出,有什么用呢?Android想要做什么?(目的)1屬性區(qū)域是由init進(jìn)程創(chuàng)建2希望其他進(jìn)程也能快速讀取屬性區(qū)域里的內(nèi)容Android怎么做到?(方法)1屬性區(qū)域創(chuàng)建于共享內(nèi)存上2客戶端進(jìn)程不知不覺得映射這塊內(nèi)存

利用了gcc的constructor屬性,這個(gè)屬性指明了一個(gè)__libc_prenit函數(shù),當(dāng)bioniclibc庫被加載時(shí),將自動(dòng)調(diào)用這個(gè)__libc_prenit,這個(gè)函數(shù)內(nèi)部就將完成共享內(nèi)存到本地進(jìn)程的映射工作。第18頁/共39頁第17頁/共39頁Diveintocodeconstructor屬性指示加載器加載該庫后,首先調(diào)用__libc_prenit函數(shù)。這一點(diǎn)和Windows上動(dòng)態(tài)庫的DllMain函數(shù)類似第19頁/共39頁第18頁/共39頁AnyQuestionsaboutinit?第20頁/共39頁第19頁/共39頁四Android常用類重難點(diǎn)分析代碼中漫天可見的RefBase、spandwp到底是什么?Inmyopinion:

1Refbase類似MFC的CObject,為C++對象之始祖。

2sp非smartpointer,而是strongpointer,wp為weakpointer。

3三者協(xié)同組建AndroidC++對象生命周期的管理和控制機(jī)能。Let’sdiveintocode……第21頁/共39頁第20頁/共39頁3.1SampleOne:初識影子對象//A沒有任何自己的功能//sp,wp對象是在{}中創(chuàng)建的,下面將先創(chuàng)建sp,然后創(chuàng)建wp//大括號結(jié)束前,先析構(gòu)wp,再析構(gòu)sp第22頁/共39頁第21頁/共39頁DiveintoCode類A從RefBase中派生。使用的是RefBase構(gòu)造函數(shù)mRefs是RefBase的成員變量,類型是weakref_impl,暫且稱之為影子對象//強(qiáng)引用計(jì)數(shù),初始值為0x1000000//弱引用計(jì)數(shù),初始值為0//該影子對象所指向的實(shí)際對象QuickQuestion:見到mStrong和mWeak,是否嗅到蛛絲馬跡?發(fā)現(xiàn)影子對象成員中有兩個(gè)引用計(jì)數(shù)?一個(gè)強(qiáng)引用,一個(gè)弱引用。如果知道引用計(jì)數(shù)和對象生死有些許關(guān)聯(lián)的話,就容易想到影子對象的作用了。

第23頁/共39頁第22頁/共39頁sp的構(gòu)造//mRefs就是剛才RefBase構(gòu)造函數(shù)中new出來的影子對象調(diào)試版的:這幾個(gè)函數(shù)將donothing!//原子操作,影子對象的弱引用計(jì)數(shù)加1continueincStrong第24頁/共39頁第23頁/共39頁//剛才增加了弱引用計(jì)數(shù),再增加強(qiáng)引用計(jì)數(shù)//下面函數(shù)為原子加1操作,并返回舊值。所以c=0x1000000,而mStrong變?yōu)?x1000001//如果c不是初始值,則表明這個(gè)對象已經(jīng)被強(qiáng)引用過一次了//下面這個(gè)是原子加操作,相當(dāng)于執(zhí)行refs->mStrong+(-0x1000000),最終mStrong=1如果是第一次引用,則調(diào)用onFirstRef,這個(gè)函數(shù)很重要,派生類可以重載這個(gè)函數(shù),完成一些初始化工作。

sp構(gòu)造后的結(jié)果:sp的出生導(dǎo)致影子對象的強(qiáng)引用計(jì)數(shù)加1,弱引用計(jì)數(shù)加1

第25頁/共39頁第24頁/共39頁wp的構(gòu)造//調(diào)用pA的createWeak,并且保存返回值到成員變量m_refs中//調(diào)用影子對象的incWeak,將導(dǎo)致影子對象的弱引用計(jì)數(shù)增加1wp構(gòu)造后的結(jié)果:影子對象的弱引用計(jì)數(shù)將增加1,所以現(xiàn)在弱引用計(jì)數(shù)為2,而強(qiáng)引用計(jì)數(shù)仍為1wp中有兩個(gè)成員變量,一個(gè)保存實(shí)際對象,另一個(gè)保存影子對象.sp只有一個(gè)成員變量用來保存實(shí)際對象,但這個(gè)實(shí)際對象內(nèi)部已包含了對應(yīng)的影子對象第26頁/共39頁第25頁/共39頁wp的析構(gòu)//調(diào)用影子對象的decWeak,由影子對象的基類實(shí)現(xiàn)//把基類指針轉(zhuǎn)換成子類(影子對象)的類型,這種做法有些違背面向?qū)ο缶幊痰乃枷?/原子減1,返回舊值,c=2,而弱引用計(jì)數(shù)從2變?yōu)?如果c為1,則弱引用計(jì)數(shù)為0,這說明沒有弱引用指向?qū)嶋H對象,需要考慮是否釋放內(nèi)存OBJECT_LIFETIME_XXX和生命周期有關(guān)系…..比較難分析….wp析構(gòu)后,弱引用計(jì)數(shù)減1。但由于此時(shí)強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)仍為1,所以沒有對象被干掉,即沒有釋放實(shí)際對象和影子對象占據(jù)的內(nèi)存。第27頁/共39頁第26頁/共39頁sp的析構(gòu)//注意,此時(shí)強(qiáng)弱引用計(jì)數(shù)都是1,下面函數(shù)調(diào)用的結(jié)果是c=1,強(qiáng)引用計(jì)數(shù)為0//mFlags為0,所以會(huì)通過deletethis把自己干掉

//注意,此時(shí)弱引用計(jì)數(shù)仍為1deletethis自殺行為沒有把影子對象干掉但我們還在decStrong中//調(diào)用前影子對象的弱引用計(jì)數(shù)為1,強(qiáng)引用計(jì)數(shù)為0,調(diào)用結(jié)束后c=1,弱引用計(jì)數(shù)為0//這次弱引用計(jì)數(shù)終于變?yōu)?,并且mFlags為0,mStrong也為0//注意,實(shí)際數(shù)據(jù)對象已經(jīng)被干掉了,所以mRefs也沒有用了,但是decStrong剛進(jìn)來//的時(shí)候就保存mRefs到refs了,所以這里的refs指向影子對象第28頁/共39頁第27頁/共39頁Sample1sumup:RefBase中有一個(gè)隱含的影子對象,該影子對象內(nèi)部有強(qiáng)弱引用計(jì)數(shù)。sp化后,強(qiáng)弱引用計(jì)數(shù)各增加1,sp析構(gòu)后,強(qiáng)弱引用計(jì)數(shù)各減1。wp化后,弱引用計(jì)數(shù)增加1,wp析構(gòu)后,弱引用計(jì)數(shù)減1。完全徹底地消滅RefBase對象,包括讓實(shí)際對象和影子對象滅亡,這些都是由強(qiáng)弱引用計(jì)數(shù)控制的,另外還要考慮flag的取值情況。當(dāng)flag為0時(shí),可得出如下結(jié)論:強(qiáng)引用為0將導(dǎo)致實(shí)際對象被delete。弱引用為0將導(dǎo)致影子對象被delete。

第29頁/共39頁第28頁/共39頁生死魔咒extendObjectLifetimeFOREVER的值是3,二進(jìn)制表示是B11,而WEAK的二進(jìn)制是B01,也就是說FOREVER包括了WEAK的情況有什么用?1flags為0,強(qiáng)引用計(jì)數(shù)控制實(shí)際對象的生命周期,弱引用計(jì)數(shù)控制影子對象的生命周期。強(qiáng)引用計(jì)數(shù)為0后,實(shí)際對象被delete。所以對于這種情況,應(yīng)記住的是,使用wp時(shí)要由弱生強(qiáng),以免收到

segmentfault信號。2flags為LIFETIME_WEAK,強(qiáng)引用計(jì)數(shù)為0,弱引用計(jì)數(shù)不為0時(shí),實(shí)際對象不會(huì)被delete。當(dāng)弱引用計(jì)數(shù)減為0時(shí),實(shí)際對象和影子對象會(huì)同時(shí)被delete。這是功德圓滿的情況。3flags為LIFETIME_FOREVER,對象將長生不老,徹底擺脫強(qiáng)弱引用計(jì)數(shù)的控制。所以你要在適當(dāng)?shù)臅r(shí)候殺死這些老妖精,免得她禍害“人間”。第30頁/共39頁第29頁/共39頁3.2題外話——無所不用其極我的煩惱:1RefBase,sp和wp:共兩個(gè)文件,1千行左右的代碼。--不多,真正參與分析的代碼應(yīng)該不到400行。2判斷極為復(fù)雜,打log也不方便,影響整個(gè)系統(tǒng)?!獙τ谶@類邏輯復(fù)雜的代碼,打log實(shí)為下策。冥思苦想……,anygoodideas?我的解決辦法:1直觀想法,要是能夠調(diào)試該多好!問題:部署gdbserver?——太麻煩2生猛一點(diǎn):代碼多且簡單,不存在依賴關(guān)系,不如……既然它的代碼不多而且簡單,那何不把它移植到臺式機(jī)的開發(fā)環(huán)境下,整一個(gè)類似的RefBase呢?步驟:1用VisualStudio,編譯和調(diào)試代碼。2至于原子操作,Windows平臺上有很直接的InterlockedExchangeXXX與之對應(yīng)。3Linux平臺上,不考慮多線程的話,將原子操作換成普通的非原子操作4如果你夠猛的話,用匯編來實(shí)現(xiàn)常用的原子操作。Tips:如果把破解代碼看成是攻城略地的話,必須學(xué)會(huì)靈活多變,而且應(yīng)力求破解方法日臻極致!

第31頁/共39頁第30頁/共39頁四Binder重難點(diǎn)分析BinderBinder聽煩了沒?見惡心了沒?有木有?有木有????要是今天聽了講座,還沒搞懂,哥傷不起啊...傷不起B(yǎng)inder本質(zhì):和Socket,Pipe一樣,是一種IPC機(jī)制為什么覺得難?或者代碼看得頭疼...完全拜Android所賜,因?yàn)樗褬I(yè)務(wù)邏輯和通信邏輯混雜在一起了OK,let’sRTFSC第32頁/共39頁第31頁/共39頁4.1時(shí)空穿越魔術(shù)揭秘獲得一個(gè)ProcessState實(shí)例調(diào)用defaultServiceManager,得到一個(gè)IServiceManager這么重要的函數(shù),放在這里...有木有看走眼的時(shí)候?BIDNER_VM_SIZE定義為(1*1024*1024)-(4096*2)=1M-8Kmmap映射一塊內(nèi)存//打開/dev/binder設(shè)備//通過ioctl方式告訴binder驅(qū)動(dòng),這個(gè)fd支持的最大線程數(shù)是15個(gè)ProcessState創(chuàng)建的結(jié)果:1打開/dev/binder設(shè)備,這就相當(dāng)于與內(nèi)核的Binder驅(qū)動(dòng)有了交互的通道。2對返回的fd使用mmap,這樣Binder驅(qū)動(dòng)就會(huì)分配一塊內(nèi)存來接收數(shù)據(jù)。由于ProcessState的惟一性,因此一個(gè)進(jìn)程只打開設(shè)備一次。第33頁/共39頁第32頁/共39頁defaultServiceManager分析//真正的gDefaultServiceManager是在這里創(chuàng)建的。handle值為0以0為變量,創(chuàng)建一個(gè)BpBinder//返回BpBinder(handle),注意,handle的值為0第34頁/共39頁第33頁/共39頁BpBinder分析//handle是0//另一個(gè)重要對象是IPCThreadState,我們稍后會(huì)詳細(xì)講解。WhatisBpBinder?BpBinder和BBinder都是Android中與Binder通信相關(guān)的代表,它們都從IBinde

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論