下面,說一點題外話,希望借此和讀者一起探討交流,共同進步。開源世界,開放平臺,關鍵就是能做到兼容并包。
1. CTS和單元測試
了解一點驅動開發的人可能都會知道,芯片的類型太多了,操作起來也不一樣。這必然導致,一個東西就得寫一套代碼,非常繁瑣,并可能反復創造低價值。
做為一個應用層開發者,我非常不希望的是,下層驅動的變動影響上層的應用(在工作中經常發現問題像病毒一樣隨意擴散)。當然,Android已經提供了HAL層,任何硬件廠商都需要實現這些接口。硬件廠商的這些代碼是需要編譯成程序來進行驗證的,可我不想拿應用層程序來做測試程序。因為應用層程序有自己的復雜邏輯,可能觸發一個聲音的bug,需要滿足很多預期的條件,否則會非常影響HAL的測試。有沒有辦法解決這一問題呢?像Google這樣的公司,面臨著很多硬件廠商,它又是怎么解決的呢?
我從CTS上看到了希望。CTS是Google為Android搞的一個兼容性測試,即不管是怎么實現硬件驅動的,反正得通過我的CTS測試。當然,CTS并不是用來測試硬件的,但是它的這種思想可以參考和借鑒。
**我很羨慕iOS的應用開發者,他們面臨的由于硬件變化導致的問題要少得多。**
其實,如果做驅動移植的同仁們能以測試驅動開發的態度來嚴格測試,可能我們這些上層開發人員就不會總懷疑是驅動的問題
了。
2. ALSA——Advanced Linux Sound Architecture
ALSA是什么,大伙兒可以網上google之。現在在大力推廣ALSA,但在Android這塊,我個人感覺它還不是很好用。“不好用”,是從上層用戶的角度說的,ALSA提供了一個用戶空間的libasound庫,而這個庫的確比較難用。不過有了Audio HAL的幫助,應用層就不用做改動了,但是實現HAL層的廠商要做的改動就比較大了。相比較而言,我覺得現在的源碼中使用的open/ioctl方法更為方便。
>[info] 說明:這可能和我做過的應用太簡單有一定關系(就是ffmpeg編解碼MP3,然后播出來即可)。而libasound提供的API較多,在權衡各種情況后,我覺得它不適合快速簡單應用的開發。
3. Desktop Check
Desktop Check雖然是一種行為,但我更覺得它的產生是基于了一種態度。DesktopCheck本意是桌面檢查。起因是在計算機技術剛興起時,程序員調試代碼非常費勁,因為那時機器配置很差,調試工具也不像現在這么發達,有時要跑到機房,預約機器然后啟動調試器,所需時間遠遠多于坐在電腦前修改一個bug的時間。對于這種情況怎么辦?為什么不像考試那樣對自己的代碼多檢查幾遍呢?自己虛擬一些應用場景,結合參數代入程序,在大腦中Trace豈不更好?這正是DesktopCheck行為的本意。
今天,很多開發人員不厭其煩得添加log,然后運行看輸出。當然,這是解決問題的一種比較好的辦法,但是在時間充裕的情況下,我還是希望開發人員能像我們前輩那樣,用Desktop Check的這種方式先反復閱讀和檢查程序,爭取在大腦中模擬程序的運行,最后才用打印log的方法來驗證自己的想法。
另外,Desktop check對提升閱讀代碼的能力有重要幫助。
* * * * *
**說明**:已記不得第一次接觸Desktop Check一詞是什么時候了,或許當時還不叫Desktop Check,但我覺得它所蘊含的思想是正確的,是頗有價值的。
* * * * *
- 前言
- 第1章 閱讀前的準備工作
- 1.1 系統架構
- 1.1.1 Android系統架構
- 1.1.2 本書的架構
- 1.2 搭建開發環境
- 1.2.1 下載源碼
- 1.2.2 編譯源碼
- 1.3 工具介紹
- 1.3.1 Source Insight介紹
- 1.3.2 Busybox的使用
- 1.4 本章小結
- 第2章 深入理解JNI
- 2.1 JNI概述
- 2.2 學習JNI的實例:MediaScanner
- 2.3 Java層的MediaScanner分析
- 2.3.1 加載JNI庫
- 2.3.2 Java的native函數和總結
- 2.4 JNI層MediaScanner的分析
- 2.4.1 注冊JNI函數
- 2.4.2 數據類型轉換
- 2.4.3 JNIEnv介紹
- 2.4.4 通過JNIEnv操作jobject
- 2.4.5 jstring介紹
- 2.4.6 JNI類型簽名介紹
- 2.4.7 垃圾回收
- 2.4.8 JNI中的異常處理
- 2.5 本章小結
- 第3章 深入理解init
- 3.1 概述
- 3.2 init分析
- 3.2.1 解析配置文件
- 3.2.2 解析service
- 3.2.3 init控制service
- 3.2.4 屬性服務
- 3.3 本章小結
- 第4章 深入理解zygote
- 4.1 概述
- 4.2 zygote分析
- 4.2.1 AppRuntime分析
- 4.2.2 Welcome to Java World
- 4.2.3 關于zygote的總結
- 4.3 SystemServer分析
- 4.3.1 SystemServer的誕生
- 4.3.2 SystemServer的重要使命
- 4.3.3 關于 SystemServer的總結
- 4.4 zygote的分裂
- 4.4.1 ActivityManagerService發送請求
- 4.4.2 有求必應之響應請求
- 4.4.3 關于zygote分裂的總結
- 4.5 拓展思考
- 4.5.1 虛擬機heapsize的限制
- 4.5.2 開機速度優化
- 4.5.3 Watchdog分析
- 4.6 本章小結
- 第5章 深入理解常見類
- 5.1 概述
- 5.2 以“三板斧”揭秘RefBase、sp和wp
- 5.2.1 第一板斧--初識影子對象
- 5.2.2 第二板斧--由弱生強
- 5.2.3 第三板斧--破解生死魔咒
- 5.2.4 輕量級的引用計數控制類LightRefBase
- 5.2.5 題外話-三板斧的來歷
- 5.3 Thread類及常用同步類分析
- 5.3.1 一個變量引發的思考
- 5.3.2 常用同步類
- 5.4 Looper和Handler類分析
- 5.4.1 Looper類分析
- 5.4.2 Handler分析
- 5.4.3 Looper和Handler的同步關系
- 5.4.4 HandlerThread介紹
- 5.5 本章小結
- 第6章 深入理解Binder
- 6.1 概述
- 6.2 庖丁解MediaServer
- 6.2.1 MediaServer的入口函數
- 6.2.2 獨一無二的ProcessState
- 6.2.3 時空穿越魔術-defaultServiceManager
- 6.2.4 注冊MediaPlayerService
- 6.2.5 秋風掃落葉-StartThread Pool和join Thread Pool分析
- 6.2.6 你徹底明白了嗎
- 6.3 服務總管ServiceManager
- 6.3.1 ServiceManager的原理
- 6.3.2 服務的注冊
- 6.3.3 ServiceManager存在的意義
- 6.4 MediaPlayerService和它的Client
- 6.4.1 查詢ServiceManager
- 6.4.2 子承父業
- 6.5 拓展思考
- 6.5.1 Binder和線程的關系
- 6.5.2 有人情味的訃告
- 6.5.3 匿名Service
- 6.6 學以致用
- 6.6.1 純Native的Service
- 6.6.2 扶得起的“阿斗”(aidl)
- 6.7 本章小結
- 第7章 深入理解Audio系統
- 7.1 概述
- 7.2 AudioTrack的破解
- 7.2.1 用例介紹
- 7.2.2 AudioTrack(Java空間)分析
- 7.2.3 AudioTrack(Native空間)分析
- 7.2.4 關于AudioTrack的總結
- 7.3 AudioFlinger的破解
- 7.3.1 AudioFlinger的誕生
- 7.3.2 通過流程分析AudioFlinger
- 7.3.3 audio_track_cblk_t分析
- 7.3.4 關于AudioFlinger的總結
- 7.4 AudioPolicyService的破解
- 7.4.1 AudioPolicyService的創建
- 7.4.2 重回AudioTrack
- 7.4.3 聲音路由切換實例分析
- 7.4.4 關于AudioPolicy的總結
- 7.5 拓展思考
- 7.5.1 DuplicatingThread破解
- 7.5.2 題外話
- 7.6 本章小結
- 第8章 深入理解Surface系統
- 8.1 概述
- 8.2 一個Activity的顯示
- 8.2.1 Activity的創建
- 8.2.2 Activity的UI繪制
- 8.2.3 關于Activity的總結
- 8.3 初識Surface
- 8.3.1 和Surface有關的流程總結
- 8.3.2 Surface之乾坤大挪移
- 8.3.3 乾坤大挪移的JNI層分析
- 8.3.4 Surface和畫圖
- 8.3.5 初識Surface小結
- 8.4 深入分析Surface
- 8.4.1 與Surface相關的基礎知識介紹
- 8.4.2 SurfaceComposerClient分析
- 8.4.3 SurfaceControl分析
- 8.4.4 writeToParcel和Surface對象的創建
- 8.4.5 lockCanvas和unlockCanvasAndPost分析
- 8.4.6 GraphicBuffer介紹
- 8.4.7 深入分析Surface的總結
- 8.5 SurfaceFlinger分析
- 8.5.1 SurfaceFlinger的誕生
- 8.5.2 SF工作線程分析
- 8.5.3 Transaction分析
- 8.5.4 關于SurfaceFlinger的總結
- 8.6 拓展思考
- 8.6.1 Surface系統的CB對象分析
- 8.6.2 ViewRoot的你問我答
- 8.6.3 LayerBuffer分析
- 8.7 本章小結
- 第9章 深入理解Vold和Rild
- 9.1 概述
- 9.2 Vold的原理與機制分析
- 9.2.1 Netlink和Uevent介紹
- 9.2.2 初識Vold
- 9.2.3 NetlinkManager模塊分析
- 9.2.4 VolumeManager模塊分析
- 9.2.5 CommandListener模塊分析
- 9.2.6 Vold實例分析
- 9.2.7 關于Vold的總結
- 9.3 Rild的原理與機制分析
- 9.3.1 初識Rild
- 9.3.2 RIL_startEventLoop分析
- 9.3.3 RIL_Init分析
- 9.3.4 RIL_register分析
- 9.3.5 關于Rild main函數的總結
- 9.3.6 Rild實例分析
- 9.3.7 關于Rild的總結
- 9.4 拓展思考
- 9.4.1 嵌入式系統的存儲知識介紹
- 9.4.2 Rild和Phone的改進探討
- 9.5 本章小結
- 第10章 深入理解MediaScanner
- 10.1 概述
- 10.2 android.process.media分析
- 10.2.1 MSR模塊分析
- 10.2.2 MSS模塊分析
- 10.2.3 android.process.media媒體掃描工作的流程總結
- 10.3 MediaScanner分析
- 10.3.1 Java層分析
- 10.3.2 JNI層分析
- 10.3.3 PVMediaScanner分析
- 10.3.4 關于MediaScanner的總結
- 10.4 拓展思考
- 10.4.1 MediaScannerConnection介紹
- 10.4.2 我問你答
- 10.5 本章小結