深入理解Andorid重難點課件_第1頁
深入理解Andorid重難點課件_第2頁
深入理解Andorid重難點課件_第3頁
深入理解Andorid重難點課件_第4頁
深入理解Andorid重難點課件_第5頁
已閱讀5頁,還剩45頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

[文檔]深入理解Andorid重難點1、合法而穩(wěn)定的權(quán)力在使用得當時很少遇到抵抗?!ぜs翰遜2、權(quán)力會使人漸漸失去溫厚善良的美德。——伯克3、最大限度地行使權(quán)力總是令人反感;權(quán)力不易確定之處始終存在著危險?!ぜs翰遜4、權(quán)力會奴化一切?!髻?、雖然權(quán)力是一頭固執(zhí)的熊,可是金子可以拉著它的鼻子走?!勘萚文檔]深入理解Andorid重難點[文檔]深入理解Andorid重難點1、合法而穩(wěn)定的權(quán)力在使用得當時很少遇到抵抗?!ぜs翰遜2、權(quán)力會使人漸漸失去溫厚善良的美德?!?、最大限度地行使權(quán)力總是令人反感;權(quán)力不易確定之處始終存在著危險。——塞·約翰遜4、權(quán)力會奴化一切。——塔西佗5、雖然權(quán)力是一頭固執(zhí)的熊,可是金子可以拉著它的鼻子走。——莎士比深入理解Android重難點解析主講人——鄧凡平大綱一JNI重難點分析 1.1注冊方法的選擇 1.2垃圾回收二init重難點分析 2.1keywords.h的有趣用法 2.2用好“DllMain函數(shù)”——客戶端Property讀取的實現(xiàn)三Android常用類重難點分析 3.1RefBase、sp和wp 3.2題外話——無所不用其極四Binder重難點分析 4.1時空穿越魔術(shù)揭秘 4.2Binder和線程的關(guān)系五Audio系統(tǒng)重難點分析 5.1AudioTrack&方法論 5.2AudioFlinger中的對象 5.3AudioPolicyService實例 5.4audio_control_block_t分析 5.5學(xué)習并實踐DesktopCheck1.1注冊方法的選擇

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

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

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

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

調(diào)用NewStringUTF創(chuàng)建一個jstring對象,它是LocalReference類型。

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

Soeasy?NotReally!JNI最好的參考資料,一切盡在不言中….

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

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

利用了gcc的constructor屬性,這個屬性指明了一個__libc_prenit函數(shù),當bioniclibc庫被加載時,將自動調(diào)用這個__libc_prenit,這個函數(shù)內(nèi)部就將完成共享內(nèi)存到本地進程的映射工作。Diveintocodeconstructor屬性指示加載器加載該庫后,首先調(diào)用__libc_prenit函數(shù)。這一點和Windows上動態(tài)庫的DllMain函數(shù)類似AnyQuestionsaboutinit?四Android常用類重難點分析代碼中漫天可見的RefBase、spandwp到底是什么?Inmyopinion:1Refbase類似MFC的CObject,為C++對象之始祖。2sp非smartpointer,而是strongpointer,wp為weakpointer。3三者協(xié)同組建AndroidC++對象生命周期的管理和控制機能。Let’sdiveintocode……3.1SampleOne:初識影子對象//A沒有任何自己的功能//sp,wp對象是在{}中創(chuàng)建的,下面將先創(chuàng)建sp,然后創(chuàng)建wp//大括號結(jié)束前,先析構(gòu)wp,再析構(gòu)spDiveintoCode類A從RefBase中派生。使用的是RefBase構(gòu)造函數(shù)mRefs是RefBase的成員變量,類型是weakref_impl,暫且稱之為影子對象//強引用計數(shù),初始值為0x1000000//弱引用計數(shù),初始值為0//該影子對象所指向的實際對象QuickQuestion:見到mStrong和mWeak,是否嗅到蛛絲馬跡?發(fā)現(xiàn)影子對象成員中有兩個引用計數(shù)?一個強引用,一個弱引用。如果知道引用計數(shù)和對象生死有些許關(guān)聯(lián)的話,就容易想到影子對象的作用了。

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

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

wp的構(gòu)造//調(diào)用pA的createWeak,并且保存返回值到成員變量m_refs中//調(diào)用影子對象的incWeak,將導(dǎo)致影子對象的弱引用計數(shù)增加1wp構(gòu)造后的結(jié)果:影子對象的弱引用計數(shù)將增加1,所以現(xiàn)在弱引用計數(shù)為2,而強引用計數(shù)仍為1wp中有兩個成員變量,一個保存實際對象,另一個保存影子對象.sp只有一個成員變量用來保存實際對象,但這個實際對象內(nèi)部已包含了對應(yīng)的影子對象wp的析構(gòu)//調(diào)用影子對象的decWeak,由影子對象的基類實現(xiàn)//把基類指針轉(zhuǎn)換成子類(影子對象)的類型,這種做法有些違背面向?qū)ο缶幊痰乃枷?/原子減1,返回舊值,c=2,而弱引用計數(shù)從2變?yōu)?如果c為1,則弱引用計數(shù)為0,這說明沒有弱引用指向?qū)嶋H對象,需要考慮是否釋放內(nèi)存OBJECT_LIFETIME_XXX和生命周期有關(guān)系…..比較難分析….wp析構(gòu)后,弱引用計數(shù)減1。但由于此時強引用計數(shù)和弱引用計數(shù)仍為1,所以沒有對象被干掉,即沒有釋放實際對象和影子對象占據(jù)的內(nèi)存。sp的析構(gòu)//注意,此時強弱引用計數(shù)都是1,下面函數(shù)調(diào)用的結(jié)果是c=1,強引用計數(shù)為0//mFlags為0,所以會通過deletethis把自己干掉//注意,此時弱引用計數(shù)仍為1deletethis自殺行為沒有把影子對象干掉但我們還在decStrong中//調(diào)用前影子對象的弱引用計數(shù)為1,強引用計數(shù)為0,調(diào)用結(jié)束后c=1,弱引用計數(shù)為0//這次弱引用計數(shù)終于變?yōu)?,并且mFlags為0,mStrong也為0//注意,實際數(shù)據(jù)對象已經(jīng)被干掉了,所以mRefs也沒有用了,但是decStrong剛進來//的時候就保存mRefs到refs了,所以這里的refs指向影子對象Sample1sumup:RefBase中有一個隱含的影子對象,該影子對象內(nèi)部有強弱引用計數(shù)。sp化后,強弱引用計數(shù)各增加1,sp析構(gòu)后,強弱引用計數(shù)各減1。wp化后,弱引用計數(shù)增加1,wp析構(gòu)后,弱引用計數(shù)減1。完全徹底地消滅RefBase對象,包括讓實際對象和影子對象滅亡,這些都是由強弱引用計數(shù)控制的,另外還要考慮flag的取值情況。當flag為0時,可得出如下結(jié)論:強引用為0將導(dǎo)致實際對象被delete。弱引用為0將導(dǎo)致影子對象被delete。

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

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

Ihaveaquestion:如果說BpBinder和通信有關(guān),是否能看到類似send,write或者和binder設(shè)備交互的函數(shù)?Sorry,IBinder家族的代碼中不能找到任何與binder設(shè)備相關(guān)的代碼障眼法——interface_castif(interface_cast==dynamic_cast||interface_cast==static_cast){如何把BpBinder*類型轉(zhuǎn)換成IServiceManager*類型?}Binder理解的重點:區(qū)分業(yè)務(wù)和通信BpBinder和通信相關(guān),通過interface_cast轉(zhuǎn)換成IServiceManager這幾個是ServiceManager所提供的業(yè)務(wù)函數(shù)夢回MFC?關(guān)鍵無比的宏!

有DECLARE,就有IMPLEMENT……So,howto“cast”Bpbinder*toIServiceManager*?終于,業(yè)務(wù)和通信這兩個對象搞到一起去了……通過DECLARE和IMPLEMENT這一對媒婆做到的….注意,這里有兩個對象….不是一家人,不進一家門…….mRemote指向BpBinder思考一下:1BpServiceManager與BpBinder結(jié)合,參與Binder通信2BnServiceManager直接從BBinder派生,參與Binder通信aswesaidbefore:BpBinder等IBinder家族中找不到和binder設(shè)備通信的代碼,那么,通信層是如何完成通信工作的呢?Diveintocode轉(zhuǎn)載請求數(shù)據(jù)的數(shù)據(jù)包remote返回BpBinder,調(diào)用它的transact函數(shù)Beverycareful:1addService做為業(yè)務(wù)層的函數(shù),打包請求數(shù)據(jù)后......2交給通信層函數(shù)來處理對于客戶端來說,業(yè)務(wù)層和通信層的分界線在這里.....請親們務(wù)必在一個高于代碼的層次來看待這個問題......BpBinder的transcat分析調(diào)用IPCThreadState函數(shù)的transactmHandle的值為0,其余幾個參數(shù)由外面?zhèn)魅虢饣螅簽槭裁碔Binder家族的代碼中沒有發(fā)現(xiàn)和binder設(shè)備交互的痕跡?原來IPCThreadState類對我們又一次隱藏了通

溫馨提示

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

評論

0/150

提交評論