• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            ++wythern++

            X presents Y for a better Z

            #

            [轉(zhuǎn)]android native層memory leak分析辦法

            原文在這里

              • adb shell setprop libc.debug.malloc 1
              • adb shell ps mediaserver
              • adb shell kill <mediaserver_pid>
            1. Call dumpMemoryAddresses(). (in MemoryLeakTrackUtil.cpp).
            2. $ adb pull /proc/<mediaserver_pid>/maps
            3. get the diff file of memory allocations
              • $ adb pull /data/000 .
              • $ adb pull /data/111 .
              • $ diff 000 111 >diff_0_1
            4. $ ./addr2func.py --root-dir=../ --maps-file=./maps diff_0_1

            posted @ 2012-07-12 19:51 wythern 閱讀(1550) | 評(píng)論 (0)編輯 收藏

            [轉(zhuǎn)】MediaScanner用法總結(jié)

            MediaScanner用法總結(jié)


            轉(zhuǎn)自這里以及這里


            -   掃描全部

             

            Java代碼  收藏代碼
            1. public void systemScan(){  
            2.         sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"  
            3.                 + Environment.getExternalStorageDirectory())));  
            4.     }  

             

             

            -  掃描某個(gè)文件  參數(shù):填入該文件的路徑

             

            Java代碼  收藏代碼
            1. public void fileScan(String file){  
            2.         Uri data = Uri.parse("file://"+file);  
            3.           
            4.         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, data));  
            5.     }  

             

             

            - 掃描文件夾 參數(shù):填入該文件夾路徑

             

            Java代碼  收藏代碼
            1. public void fileScan(String file){  
            2.         Uri data = Uri.parse("file://"+file);  
            3.           
            4.         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, data));  
            5.     }  
            6.       
            7.     public void folderScan(String path){  
            8.         File file = new File(path);  
            9.           
            10.         if(file.isDirectory()){  
            11.             File[] array = file.listFiles();  
            12.               
            13.             for(int i=0;i<array.length;i++){  
            14.                 File f = array[i];  
            15.                   
            16.                 if(f.isFile()){//FILE TYPE  
            17.                     String name = f.getName();  
            18.                       
            19.                     if(name.contains(".mp3")){  
            20.                         fileScan(f.getAbsolutePath());  
            21.                     }  
            22.                 }  
            23.                 else {//FOLDER TYPE  
            24.                     folderScan(f.getAbsolutePath());  
            25.                 }  
            26.             }  
            27.         }  
            28.     }  

             

             

             

             

            posted @ 2012-06-04 20:38 wythern 閱讀(398) | 評(píng)論 (0)編輯 收藏

            [轉(zhuǎn)]eclipse中幾種加入jar包方式的區(qū)別

            原文鏈接:
            http://yilin.iteye.com/blog/941062


                 Java中的Jar是如此的重要,以至于沒(méi)有他們,我們就不能做出如此藝術(shù)的程序:封裝、模塊化、復(fù)用等等(無(wú)ant、marven方式) 。

            今天,我就來(lái)整理一些有關(guān)項(xiàng)目中的jar包添加管理的方法以及常見(jiàn)問(wèn)題的解決:

            1、jar導(dǎo)入到我們的web項(xiàng)目中的classpath下

                 1)這里呢,一種方法是,直接用MyEclipse里自帶的相關(guān)的項(xiàng)目jar包,右擊項(xiàng)目“MyEclipse”菜單,選擇對(duì)應(yīng)的jar包就OK了,例 “Add Spring Capabilities”,并且可以設(shè)置Spring的一些配置信息,不錯(cuò)的可視化操作;

                 2)添加外部的jar包到web項(xiàng)目的lib包下,右擊項(xiàng)目“Properties”-->“Java Build Path”-->“Libraries”選項(xiàng)卡(當(dāng)然了,此操作下,不僅僅這一種添加jar包的方式);

                 3)自己手動(dòng)拷貝jar文件到項(xiàng)目的lib包下,具體操作只要把要添加的jar文件拷貝到MyEclipse中的workspace下的lib包里就好了;

            至此,jar文件的添加就OK了,so easy!jar是加進(jìn)去了,但這幾種有什么區(qū)別,以后如何管理呢,接下來(lái)看看第2點(diǎn)

             

            2、三種jar包添加方式,都行得通,很OK,那么要如何擇決呢

                 1)這種方式,jar文件直接鏈接到MyEclipse的文件下,并沒(méi)有拷貝到WEB-INF/lib目錄下,不得用項(xiàng)目的發(fā)布、移植,可能會(huì)出現(xiàn)jar找不到的情形;

                 2)選擇性比較的強(qiáng),可以隨意的加jar包,只要在你本機(jī)存在就可以了,鏈接的也是jar文件的絕對(duì)路徑,缺點(diǎn)同1;

                 3)直接添加到WEB-INF/lib目錄下,移植性強(qiáng),可操作性也強(qiáng)。

            總而言之,第3)種jar包導(dǎo)入方式,個(gè)人覺(jué)得還是不錯(cuò)的了!

             

            3、顯示/隱藏項(xiàng)目里的jar文件

                 不同的開(kāi)發(fā)人員,都有著他固有的習(xí)慣,有的人就覺(jué)得把jar包顯示在開(kāi)發(fā)視圖里太礙眼,看起來(lái)不舒服,復(fù)雜。而有些人呢,他就想研究看看到底運(yùn)用了哪些技 術(shù),導(dǎo)了哪些jar包,并且通過(guò)點(diǎn)擊jar包里的class文件直接查看源碼(假設(shè)先前有導(dǎo)入源碼)。所以呢,這里就牽涉到了一個(gè)jar包的顯示與隱藏問(wèn) 題了:在Package Explorer這個(gè)窗體中,右上角有個(gè)下拉小三角,點(diǎn)擊-->“Filters”-->“Name filter patterns(matching names will be hidden)”,在這一選項(xiàng)下填有*.jar,勾上復(fù)選框即表示這一類(lèi)的文件不顯示,多個(gè)類(lèi)型之間可用“,”分隔。

             

            4、在Eclipse工程的Java Build Path設(shè)置中,可以通過(guò)加入第三方的jar包,但是,我發(fā)現(xiàn)是有好幾種方法來(lái)完成這個(gè)操作的,有“Add jars”,“Add Externel jars”,“Add library”,“Add Classes Loader”等,這幾種方式有什么區(qū)別嗎?
            add jar是表示從你的工程里添加JAR,前提是你把jar已經(jīng)放到自己的工程目錄里。
            add external jar表示這個(gè)jar的位置需要URI來(lái)定位,需要給出全路徑。
            add library 是一些已經(jīng)定義好的jar的集合,因?yàn)樗鼈兘?jīng)常是一起用,所以簡(jiǎn)化了些操作,比如你做RCP開(kāi)發(fā)的時(shí)候就會(huì)有個(gè)plugin library包含了運(yùn)行工程所需要的基本插件。
            Add classes Loader -- 這個(gè)應(yīng)該是 add class folder吧?這個(gè)跟添加jar是一個(gè)意思,就是告訴ClassLoader去哪找class

             

            5.當(dāng)出現(xiàn)java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener類(lèi)似這種找不到Listener的異常 時(shí),要切記spring的jar包一定要放在工程的lib下這樣才能避免這個(gè)錯(cuò)誤的發(fā)生。

            補(bǔ)充:雖說(shuō)無(wú)論用什么方式導(dǎo)入包在本地運(yùn)行都是一樣的,但實(shí)事上我運(yùn)行時(shí),有的只有Java Build Path才起作用,有的只有導(dǎo)入到lib下才行。Java Build Path導(dǎo)入包和把包復(fù)制到lib下是有區(qū)別的,它倆其實(shí)不會(huì)沖突,也沒(méi)有什么關(guān)系的,Java Build Path是我們編譯需要的包,在比如在import ***.***.***時(shí)如果沒(méi)用Java Build Path導(dǎo)入包的話(huà)類(lèi)里面就有紅叉,說(shuō)不識(shí)別這個(gè)類(lèi);導(dǎo)入到lib下是程序運(yùn)行時(shí)需要的包,即便用Java Build Path導(dǎo)入過(guò)的包,沒(méi)放到lib下,運(yùn)行項(xiàng)目時(shí)會(huì)出現(xiàn)ClassNotFoundException的異常。

            posted @ 2012-05-17 15:00 wythern 閱讀(11359) | 評(píng)論 (0)編輯 收藏

            【轉(zhuǎn)】Android 調(diào)試技術(shù)

            原文鏈接:
            http://www.bobbog.com/archives/19


            Android 調(diào)試技術(shù)

            by bob

            一、JAVA層單步調(diào)試

            參見(jiàn)“用eclipse單步調(diào)試Laucher
            參見(jiàn)“用eclipse編譯調(diào)試adnroid的Browser

            二、Native層單步調(diào)試

            參見(jiàn)“使用GDB 單步調(diào)試Android本地代碼

            三、JAVA層堆棧打印

            1. 在指定的函數(shù)內(nèi)打印相關(guān)java調(diào)用

            Log.d(TAG,Log.getStackTraceString(new Throwable()));

            2. 普通JAVA進(jìn)程堆棧

            ActivityManagerService.dumpStackTraces

            保存在系統(tǒng)設(shè)置dalvik.vm.stack-trace-file指定的文件data/anr/traces.txt中。可以包含多個(gè)進(jìn)程堆棧信息。

            3. 內(nèi)核進(jìn)程堆棧

            dumpKernelStackTraces,該函數(shù)為私有函數(shù),不可調(diào)用。
            代碼在frameworks/base/services/java/com/android/server/Watchdog.java
            保存在系統(tǒng)設(shè)置dalvik.vm.stack-trace-file指定的文件data/anr/traces.txt中。

            4. 出異常時(shí)打印當(dāng)前堆棧

            Exception::printStackTrace()

            try {  ... } catch (RemoteException e) {   e.printStackTrace();   ... }

            5. 輸出指定進(jìn)程的堆棧

            Process.sendSignal(pid, Process.SIGNAL_QUIT)

            保存在data/anr/traces.txt。
            這個(gè)只對(duì)java進(jìn)程有效,由dalvikvm的SignalCatcher.c處理。

            四、Native層堆棧打印

            1. CallStack

            使用方式:

            #include <utils/CallStack.h> ... CallStack stack; stack.update(); stack.dump("");  // the parameter is prefix of dump

            在使用之前需要修改system/core/include/arch/linux-arm/AndroidConfig.h

            #define HAVE_DLADDR 1 #define HAVE_CXXABI 1

            并在文件frameworks/base/libs/utils/Android.mk中大約105行(LOCAL_SHARED_LIBRARIES)后添加

            ifeq ($(TARGET_OS),linux) LOCAL_SHARED_LIBRARIES += libdl endif

            重新編譯,push生成的libutils.so到/system/lib/目錄下,重啟設(shè)備。

            五、JAVA異常分析

            這個(gè)android會(huì)輸出信息到logcat。容易分析。

            六、Natvie異常分析

            native進(jìn)程異常會(huì)導(dǎo)致
            debuggerd會(huì)輸出信息到logcat并保存到/data/tombstones。
            可以修改system/core/debuggerd/debuggerd.c中dump_stack_and_code的代碼滿(mǎn)足更深的調(diào)試信息需求。

            七、日志Log系統(tǒng)

            在java中使用

            import android.util.Log; ... Log.d(TAG,"log info");

            在Native代碼中使用

            #define LOG_TAG "YOUR_LOGTAG" ... #include <utils/Log.h> #define LOG_NDEBUG 0 ... LOGD("log info");

            或者

            Log.d(LOG_TAG,“log info”);

            使用adb logcat時(shí)可以只顯示特定類(lèi)別的LOG,還可以通過(guò)參數(shù) -v threadtime 顯示線(xiàn)程號(hào)及時(shí)間信息。
            普通標(biāo)準(zhǔn)輸出轉(zhuǎn)為L(zhǎng)ogcat

            #system/bin/logwrapper 進(jìn)程名

            八、其他調(diào)試手段(命令行)

            1. 打印指定JAVA進(jìn)程的堆棧到文件中

            #kill -3 pid

            這里的3就是3.5節(jié)的Process.SIGNAL_QUIT。
            輸出在data/anr/traces.txt文件中。
            這個(gè)只對(duì)java進(jìn)程有效,由dalvikvm處理。

            2. 打印指定進(jìn)程的堆棧到Logcat

            #kill -11 pid 或者 #kill -7 pid

            這個(gè)有時(shí)有效。其原理是利用了(六)節(jié)的機(jī)制。
            可以用adb logcat看堆棧調(diào)用輸出。

            3. 打印指定進(jìn)程的系統(tǒng)調(diào)用

            #strace -f -p pid -o output

            主要輸出文件、SOCKET、鎖等系統(tǒng)操作的信息。
            -f表示跟蹤所有子進(jìn)程.
            -o輸出log到指定文件,可不用。

            posted @ 2012-04-16 19:02 wythern 閱讀(5681) | 評(píng)論 (0)編輯 收藏

            編譯android出現(xiàn)"too many open files"的解決辦法

            # vi /etc/sysctl.conf
            Append a config directive as follows:
            fs.file-max = 100000

            # vi /etc/security/limits.conf
            Set httpd user soft and hard limits as follows:
            httpd soft nofile 4096
            httpd hard nofile 10240

            Save and close the file. To see limits, enter:
            # su - httpd
            $ ulimit -Hn
            $ ulimit -Sn

            PS:好像需要重啟才能生效


            參考資料
            http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

            posted @ 2012-02-06 15:28 wythern 閱讀(2265) | 評(píng)論 (0)編輯 收藏

            [轉(zhuǎn)]Android SurfaceFlinger中的SharedClient -- 客戶(hù)端(Surface)和服務(wù)端(Layer)之間的顯示緩沖區(qū)管理

            原文:
            http://blog.csdn.net/droidphone/article/details/5972568


              SurfaceFlinger在系統(tǒng)啟動(dòng)階段作為系統(tǒng)服務(wù)被加載。應(yīng)用程序中的每個(gè)窗口,對(duì)應(yīng)本地代碼中的Surface,而Surface又對(duì)應(yīng)于 SurfaceFlinger中的各個(gè)Layer,SurfaceFlinger的主要作用是為這些Layer申請(qǐng)內(nèi)存,根據(jù)應(yīng)用程序的請(qǐng)求管理這些 Layer顯示、隱藏、重畫(huà)等操作,最終由SurfaceFlinger把所有的Layer組合到一起,顯示到顯示器上。當(dāng)一個(gè)應(yīng)用程序需要在一個(gè) Surface上進(jìn)行畫(huà)圖操作時(shí),首先要拿到這個(gè)Surface在內(nèi)存中的起始地址,而這塊內(nèi)存是在SurfaceFlinger中分配的,因?yàn)?SurfaceFlinger和應(yīng)用程序并不是運(yùn)行在同一個(gè)進(jìn)程中,如何在應(yīng)用客戶(hù)端(Surface)和服務(wù)端(SurfaceFlinger - Layer)之間傳遞和同步顯示緩沖區(qū)?這正是本文要討論的內(nèi)容。

            Surface的創(chuàng)建過(guò)程

            我們先看看Android如何創(chuàng)建一個(gè)Surface,下面的序列圖展示了整個(gè)創(chuàng)建過(guò)程。

                                                                          圖一   Surface的創(chuàng)建過(guò)程

            創(chuàng)建Surface的過(guò)程基本上分為兩步:

            1. 建立SurfaceSession

            第一步通常只執(zhí)行一次,目的是創(chuàng)建一個(gè)SurfaceComposerClient的實(shí)例,JAVA層通過(guò)JNI調(diào)用本地代碼,本地代碼創(chuàng)建一個(gè) SurfaceComposerClient的實(shí)例,SurfaceComposerClient通過(guò)ISurfaceComposer接口調(diào)用 SurfaceFlinger的createConnection,SurfaceFlinger返回一個(gè)ISurfaceFlingerClient接 口給SurfaceComposerClient,在createConnection的過(guò)程中,SurfaceFlinger創(chuàng)建了用于管理緩沖區(qū)切換 的SharedClient,關(guān)于SharedClient我們下面再介紹,最后,本地層把SurfaceComposerClient的實(shí)例返回給 JAVA層,完成SurfaceSession的建立。

             

            2. 利用SurfaceSession創(chuàng)建Surface

            JAVA層通過(guò)JNI調(diào)用本地代碼Surface_Init(),本地代碼首先取得第一步創(chuàng)建的SurfaceComposerClient實(shí)例, 通過(guò)SurfaceComposerClient,調(diào)用ISurfaceFlingerClient接口的createSurface方法,進(jìn)入 SurfaceFlinger,SurfaceFlinger根據(jù)參數(shù),創(chuàng)建不同類(lèi)型的Layer,然后調(diào)用Layer的setBuffers()方法, 為該Layer創(chuàng)建了兩個(gè)緩沖區(qū),然后返回該Layer的ISurface接口,SurfaceComposerClient使用這個(gè)ISurface接 口創(chuàng)建一個(gè)SurfaceControl實(shí)例,并把這個(gè)SurfaceControl返回給JAVA層。

             

            由此得到以下結(jié)果:

            • JAVA層的Surface實(shí)際上對(duì)應(yīng)于本地層的SurfaceControl對(duì)象,以后本地代碼可以使用JAVA傳入的SurfaceControl對(duì)象,通過(guò)SurfaceControl的getSurface方法,獲得本地Surface對(duì)象;
            • Android為每個(gè)Surface分配了兩個(gè)圖形緩沖區(qū),以便實(shí)現(xiàn)Page-Flip的動(dòng)作;
            • 建立SurfaceSession時(shí),SurfaceFlinger創(chuàng)建了用于管理兩個(gè)圖形緩沖區(qū)切換的SharedClient對(duì) 象,SurfaceComposerClient可以通過(guò)ISurfaceFlingerClient接口的getControlBlock()方法獲得 這個(gè)SharedClient對(duì)象,查看SurfaceComposerClient的成員函數(shù)_init:

             

            1. void SurfaceComposerClient::_init(  
            2.         const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)  
            3. {  
            4.     ......  
            5.     mClient = conn;  
            6.     if (mClient == 0) {  
            7.         mStatus = NO_INIT;  
            8.         return;  
            9.     }  
            10.   
            11.     mControlMemory = mClient->getControlBlock();  
            12.     mSignalServer = sm;  
            13.     mControl = static_cast<SharedClient *>(mControlMemory->getBase());  
            14. }  

            獲得Surface對(duì)應(yīng)的顯示緩沖區(qū)

            雖然在SurfaceFlinger在創(chuàng)建Layer時(shí)已經(jīng)為每個(gè)Layer申請(qǐng)了兩個(gè)緩沖區(qū),但是此時(shí)在JAVA層并看不到這兩個(gè)緩沖 區(qū),JAVA層要想在Surface上進(jìn)行畫(huà)圖操作,必須要先把其中的一個(gè)緩沖區(qū)綁定到Canvas中,然后所有對(duì)該Canvas的畫(huà)圖操作最后都會(huì)畫(huà)到 該緩沖區(qū)內(nèi)。下圖展現(xiàn)了綁定緩沖區(qū)的過(guò)程:

                                                                                        圖二  綁定緩沖區(qū)的過(guò)程

                開(kāi)始在Surface畫(huà)圖前,Surface.java會(huì)先調(diào)用lockCanvas()來(lái)得到要進(jìn)行畫(huà)圖操作的Canvas,lockCanvas會(huì)進(jìn) 一步調(diào)用本地層的Surface_lockCanvas,本地代碼利用JAVA層傳入的SurfaceControl對(duì)象,通過(guò)getSurface() 取得本地層的Surface對(duì)象,接著調(diào)用該Surface對(duì)象的lock()方法,lock()返回了改Surface的信息,其中包括了可用緩沖區(qū)的 首地址vaddr,該vaddr在Android的2D圖形庫(kù)Skia中,創(chuàng)建了一個(gè)bitmap,然后通過(guò)Skia庫(kù)中Canvas的 API:Canvas.setBitmapDevice(bitmap),把該bitmap綁定到Canvas中,最后把這個(gè)Canvas返回給JAVA 層,這樣JAVA層就可以在該Canvas上進(jìn)行畫(huà)圖操作,而這些畫(huà)圖操作最終都會(huì)畫(huà)在以vaddr為首地址的緩沖區(qū)中。

                再看看在Surface的lock()方法中做了什么:

            • dequeueBuffer(&backBuffer)獲取backBuffer
              • SharedBufferClient->dequeue()獲得當(dāng)前空閑緩沖區(qū)的編號(hào)
              • 通過(guò)緩沖區(qū)編號(hào)獲得真正的GraphicBuffer:backBuffer
              • 如果還沒(méi)有對(duì)Layer中的buffer進(jìn)行映射(Mapper),getBufferLocked通過(guò)ISurface接口重新重新映射
            • 獲取frontBuffer
            • 根據(jù)兩個(gè)Buffer的更新區(qū)域,把frontBuffer的內(nèi)容拷貝到backBuffer中,這樣保證了兩個(gè)Buffer中顯示內(nèi)容的同步
            • backBuffer->lock() 獲得backBuffer緩沖區(qū)的首地址vaddr
            • 通過(guò)info參數(shù)返回vaddr

            釋放Surface對(duì)應(yīng)的顯示緩沖區(qū)

            畫(huà)圖完成后,要想把Surface的內(nèi)容顯示到屏幕上,需要把Canvas中綁定的緩沖區(qū)釋放,并且把該緩沖區(qū)從變成可投遞(因?yàn)槟J(rèn)只有兩個(gè) buffer,所以實(shí)際上就是變成了frontBuffer),SurfaceFlinger的工作線(xiàn)程會(huì)在適當(dāng)?shù)乃⑿聲r(shí)刻,把系統(tǒng)中所有的 frontBuffer混合在一起,然后通過(guò)OpenGL刷新到屏幕上。下圖展現(xiàn)了解除綁定緩沖區(qū)的過(guò)程:

                                                                             圖三  解除綁定緩沖區(qū)的過(guò)程

            • JAVA層調(diào)用unlockCanvasAndPost
            • 進(jìn)入本地代碼:Surface_unlockCanvasAndPost
            • 本地代碼利用JAVA層傳入的SurfaceControl對(duì)象,通過(guò)getSurface()取得本地層的Surface對(duì)象
            • 綁定一個(gè)空的bitmap到Canvas中
            • 調(diào)用Surface的unlockAndPost方法
              • 調(diào)用GraphicBuffer的unlock(),解鎖緩沖區(qū)
              • 在queueBuffer()調(diào)用了SharedBufferClient的queue(),把該緩沖區(qū)更新為可投遞狀態(tài)

            SharedClient 和 SharedBufferStack

            從前面的討論可以看到,Canvas綁定緩沖區(qū)時(shí),要通過(guò)SharedBufferClient的dequeue方法取得空閑的緩沖區(qū),而解除綁定 并提交緩沖區(qū)投遞時(shí),最后也要調(diào)用SharedBufferClient的queue方法通知SurfaceFlinger的工作線(xiàn)程。實(shí)際上,在 SurfaceFlinger里,每個(gè)Layer也會(huì)關(guān)聯(lián)一個(gè)SharedBufferServer,SurfaceFlinger的工作線(xiàn)程通過(guò) SharedBufferServer管理著Layer的緩沖區(qū),在SurfaceComposerClient建立連接的階 段,SurfaceFlinger就已經(jīng)為該連接創(chuàng)建了一個(gè)SharedClient 對(duì)象,SharedClient 對(duì)象中包含了一個(gè)SharedBufferStack數(shù)組,數(shù)組的大小是31,每當(dāng)創(chuàng)建一個(gè)Surface,就會(huì)占用數(shù)組中的一個(gè) SharedBufferStack,然后SurfaceComposerClient端的Surface會(huì)創(chuàng)建一個(gè) SharedBufferClient和該SharedBufferStack關(guān)聯(lián),而SurfaceFlinger端的Layer也會(huì)創(chuàng)建 SharedBufferServer和SharedBufferStack關(guān)聯(lián),實(shí)際上每對(duì) SharedBufferClient/SharedBufferServer是控制著同一個(gè)SharedBufferStack對(duì)象,通過(guò) SharedBufferStack,保證了負(fù)責(zé)對(duì)Surface的畫(huà)圖操作的應(yīng)用端和負(fù)責(zé)刷新屏幕的服務(wù)端(SurfaceFlinger)可以使用不 同的緩沖區(qū),并且讓他們之間知道對(duì)方何時(shí)鎖定/釋放緩沖區(qū)。

            SharedClient和SharedBufferStack的代碼和頭文件分別位于:

            /frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp

            /frameworks/base/include/private/surfaceflinger/SharedBufferStack.h

             

             

                                                                                   圖四    客戶(hù)端和服務(wù)端緩沖區(qū)管理

                 繼續(xù)研究SharedClient、SharedBufferStack、SharedBufferClient、SharedBufferServer的誕生過(guò)程。

                1. SharedClient

            •     在createConnection階段,SurfaceFlinger創(chuàng)建Client對(duì)象:
            1. sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()  
            2. {  
            3.     Mutex::Autolock _l(mStateLock);  
            4.     uint32_t token = mTokens.acquire();  
            5.   
            6.     sp<Client> client = new Client(token, this);  
            7.     if (client->ctrlblk == 0) {  
            8.         mTokens.release(token);  
            9.         return 0;  
            10.     }  
            11.     status_t err = mClientsMap.add(token, client);  
            12.     if (err < 0) {  
            13.         mTokens.release(token);  
            14.         return 0;  
            15.     }  
            16.     sp<BClient> bclient =  
            17.         new BClient(this, token, client->getControlBlockMemory());  
            18.     return bclient;  
            19. }  
            • 再進(jìn)入Client的構(gòu)造函數(shù)中,它分配了4K大小的共享內(nèi)存,并在這塊內(nèi)存上構(gòu)建了SharedClient對(duì)象:
            1. Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)  
            2.     : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)  
            3. {  
            4.     const int pgsize = getpagesize();  
            5.     const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));  
            6.   
            7.     mCblkHeap = new MemoryHeapBase(cblksize, 0,  
            8.             "SurfaceFlinger Client control-block");  
            9.   
            10.     ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());  
            11.     if (ctrlblk) { // construct the shared structure in-place.  
            12.         new(ctrlblk) SharedClient;  
            13.     }  
            14. }  
            • 回到createConnection中,通過(guò)Client的getControlBlockMemory()方法獲得共享內(nèi)存塊的 IMemoryHeap接口,接著創(chuàng)建ISurfaceFlingerClient的子類(lèi)BClient,BClient的成員變量mCblk保存了 IMemoryHeap接口指針;
            • 把BClient返回給SurfaceComposerClient,SurfaceComposerClient通過(guò) ISurfaceFlingerClient接口的getControlBlock()方法獲得IMemoryHeap接口指針,同時(shí)保存在 SurfaceComposerClient的成員變量mControlMemory中;
            • 繼續(xù)通過(guò)IMemoryHeap接口的getBase ()方法獲取共享內(nèi)存的首地址,轉(zhuǎn)換為SharedClient指針后保存在SurfaceComposerClient的成員變量mControl中;
            • 至此,SurfaceComposerClient的成員變量mControl和SurfaceFlinger::Client.ctrlblk指向了同一個(gè)內(nèi)存塊,該內(nèi)存塊上就是SharedClient對(duì)象。 

                2. SharedBufferStack、SharedBufferServer、SharedBufferClient

                SharedClient對(duì)象中有一個(gè)SharedBufferStack數(shù)組:

                SharedBufferStack surfaces[ NUM_LAYERS_MAX ];

                NUM_LAYERS_MAX 被定義為31,這樣保證了SharedClient對(duì)象的大小正好滿(mǎn)足4KB的要求。創(chuàng)建一個(gè)新的Surface時(shí),進(jìn)入SurfaceFlinger的 createSurface函數(shù)后,先取在createConnection階段創(chuàng)建的Client對(duì)象,通過(guò)Client在 0--NUM_LAYERS_MAX 之間取得一個(gè)尚未被使用的編號(hào),這個(gè)編號(hào)實(shí)際上就是SharedBufferStack數(shù)組的索引:

            1. int32_t id = client->generateId(pid);  
              

             然后以Client對(duì)象和索引值以及其他參數(shù),創(chuàng)建不同類(lèi)型的Layer對(duì)象,一普通的Layer對(duì)象為例:

            1. layer = createNormalSurfaceLocked(client, d, id,  
            2.                         w, h, flags, format);  

            在createNormalSurfaceLocked中創(chuàng)建Layer對(duì)象:

            1. sp<Layer> layer = new Layer(this, display, client, id);  

            構(gòu)造Layer時(shí)會(huì)先構(gòu)造的父類(lèi)LayerBaseClient,LayerBaseClient中創(chuàng)建了SharedBufferServer對(duì) 象,SharedBufferStack 數(shù)組的索引值和SharedClient被傳入SharedBufferServer對(duì)象中。

            1. LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,  
            2.         const sp<Client>& client, int32_t i)  
            3.     : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),  
            4.       mIdentity(uint32_t(android_atomic_inc(&sIdentity)))  
            5. {  
            6.     lcblk = new SharedBufferServer(  
            7.             client->ctrlblk, i, NUM_BUFFERS,  
            8.             mIdentity);  
            9. }  

             

                自此,Layer通過(guò)lcblk成員變量(SharedBufferServer)和SharedClient共享內(nèi)存區(qū)建立了關(guān)聯(lián),并且每個(gè)Layer對(duì)應(yīng)于SharedBufferStack 數(shù)組中的一項(xiàng)。

                回到SurfaceFlinger的客戶(hù)端Surface.cpp中,Surface的構(gòu)造函數(shù)如下:

            1. Surface::Surface(const sp<SurfaceControl>& surface)  
            2.     : mClient(surface->mClient), mSurface(surface->mSurface),  
            3.       mToken(surface->mToken), mIdentity(surface->mIdentity),  
            4.       mFormat(surface->mFormat), mFlags(surface->mFlags),  
            5.       mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),  
            6.       mWidth(surface->mWidth), mHeight(surface->mHeight)  
            7. {  
            8.     mSharedBufferClient = new SharedBufferClient(  
            9.             mClient->mControl, mToken, 2, mIdentity);  
            10.   
            11.     init();  
            12. }  

            SharedBufferClient構(gòu)造參數(shù)mClient->mControl就是共享內(nèi)存塊中的SharedClient對(duì)象,mToken就是SharedBufferStack 數(shù)組索引值。

            到這里我們終于知道,Surface中的mSharedBufferClient成 員和Layer中的lcblk成員(SharedBufferServer),通過(guò)SharedClient中的同一個(gè) SharedBufferStack,共同管理著Surface(Layer)中的兩個(gè)緩沖區(qū)。



            一并參考:

            http://wenku.baidu.com/view/0243844bc850ad02de8041e6.html

             

            posted @ 2011-11-05 20:47 wythern 閱讀(427) | 評(píng)論 (0)編輯 收藏

            [轉(zhuǎn)]git 合并多個(gè)commit

            [source]
            http://blog.csdn.net/lynnos/article/details/6287135


            $ git reset --soft HEAD^1 (多個(gè)就是N了)

            $ git commit --amend

            posted @ 2011-08-09 16:41 wythern 閱讀(1231) | 評(píng)論 (0)編輯 收藏

            [轉(zhuǎn)]在Emacs里面如何替換有換行符的字符串

            [Source] 
            http://zh-cn.w3support.net/index.php?db=so&id=613022

            1. M-x replace-string ; \n
               will replace ";" with 2 characters "\n".

            2. M-x replace-regex ; \n
               get a error msg: Invalid use of `\' in replacement text.
               in this mode use C-q C-j to insert a RET into the string you current edited for replace/replaced.

            The author also said that you could paste a RET into the string for instead the method above, but i have not tested that.




            posted @ 2011-07-01 10:54 wythern 閱讀(1902) | 評(píng)論 (0)編輯 收藏

            Android Services in init.rc


            碰上一個(gè)寫(xiě)在init.rc里面的service不能自動(dòng)啟動(dòng)的問(wèn)題,加上class好了。
            service yourservice /sbin/yourservice
               class core
               user adb
               group adb
            class <name>
               Specify a class name for the service.  All services in a
               named class may be started or stopped together.  A service
               is in the class "default" if one is not specified via the
               class option.

            看起來(lái)是因?yàn)?div>All services in a named class may be started or stopped together.
            而如果default的class都沒(méi)有起來(lái)的話(huà),這個(gè)service也就不會(huì)自動(dòng)啟動(dòng)了
            所以 class_start default. 還是有用的....


            Ref:
            [Android init language]
            http://www.netmite.com/android/mydroid/1.6/system/core/init/readme.txt

            posted @ 2011-06-29 15:37 wythern 閱讀(1046) | 評(píng)論 (0)編輯 收藏

            Usage of zero element array

            Source: http://stackoverflow.com/questions/4255193/declaring-zero-size-vector

            This is called a flexible array member, and in C99 is written as char bar[];, and in C89 was written as char bar[1];, and which some compilers would let you write as char bar[0];. Basically, you only use pointers to the structure, and allocate them all with an amount of extra space at the end:

            const size_t i = sizeof("Hello, world!");
            struct foo *p = malloc(offsetof(struct foo, bar) + i);
            memcpy(p->bar, "Hello, world!", i);
            // initialize other members of p
            printf("%s\n", p->bar);

            That way, p->bar stores a string whose size isn't limited by an array declaration, but which is still all done in the same allocation as the rest of the struct (rather than needing the member to be a char * and need two mallocs and two frees to set it up).

            好處:連續(xù)(虛擬)內(nèi)存空間以及僅需一次的free操作。

            posted @ 2011-05-04 13:37 wythern 閱讀(184) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題
            共6頁(yè): 1 2 3 4 5 6 
            久久综合久久综合久久综合| 99久久精品免费看国产免费| 久久久久婷婷| 亚洲国产精品无码久久| 久久国产精品99精品国产987| 性做久久久久久久久浪潮| 亚洲国产一成人久久精品| 国产欧美一区二区久久| 亚洲国产日韩欧美久久| 久久99精品久久久久久不卡| 粉嫩小泬无遮挡久久久久久| 午夜精品久久久久久| 成人亚洲欧美久久久久| 久久国产精品99精品国产987| 亚洲精品国产自在久久| 久久精品国产亚洲欧美| 99久久国产宗和精品1上映| 亚洲va久久久久| 久久成人18免费网站| 久久久久免费看成人影片| 精品久久久久久无码专区| 午夜肉伦伦影院久久精品免费看国产一区二区三区| 一本一本久久A久久综合精品| 久久99精品久久久久久秒播| 久久亚洲美女精品国产精品| 精品国产VA久久久久久久冰 | 久久激情亚洲精品无码?V| 久久精品国产99久久无毒不卡| 精品久久久一二三区| 久久婷婷五月综合色奶水99啪| 亚洲国产精品久久久久| 精品永久久福利一区二区| 亚洲中文久久精品无码ww16| 亚洲欧洲久久久精品| 午夜精品久久久久久影视777| 午夜精品久久久久成人| 无夜精品久久久久久| 免费久久人人爽人人爽av| 一本综合久久国产二区| 精品久久人人爽天天玩人人妻| 久久99热这里只有精品66|