BeagleBoard 是 0xlab 內部用來驗證 ARM 硬體的參考平台,這兩個月內,我們整合了若干無線通訊大廠的 WLAN/Bluetooth 晶片組,而 TI OMAP 353x SoC 的表現著實令人驚豔。初步對 ARMv7 做了優化後,我們進一步運用 OMAP DSP 與 Display Subsystem 的特性,下圖即是在 Android 上硬體加速的 OpenGL|ES 與影片播放,
透過 DVI-HDMI 到顯示器,呈現 1024x768 的解析度,圖上方可見 Android 的狀態資訊列,而最上層就是 video overlay,而下方是 OpenGL|ES 的繪圖區,被遮蔽的最底層則為 Android surface。TI OMAP 3 整體示意圖可參考下圖:
硬體支援三個 stacked overlays,其中 Video 2 和 Video 1 overlay 提供 RGB 及 YCbCr/YUV 的 color space,搭配 TI DSP 與 ARM NEON 加速指令集,可帶來相當順暢且華麗的展現。以下是稍早所作的 OpenGL|ES 與 HW video overlay 人機介面展示影片:
在 Android/OMAP 展現硬體加速的 OpenGL|ES 與影片播放
針對 ARMv7 改進的 Android
前文「升級 Android 內建 GNU Toolchain 到 gcc 4.4」提及使用更新的編譯器平台,現在追蹤的是 gcc 4.4/4.5,不排除引入 LLVM,這些準備都是為了允許施加更多優化、展現平台的特性,而在 Android 的 build system 也需要作一些更動,至少涵蓋以下:
- 針對硬體平台的編譯參數
- Dalvik machine-dependent interpreter implementation (mterp)
- 針對硬體特徵優化的關鍵軟體,如 BlueZ 中處理音訊 Bluetooth low-complexity, subband codec (SBC) 的實做
- 設定 gcc 編譯參數為 "-march=armv7-a -mtune=cortex-a8 -mfpu=neon",適用於 BeagleBoard (TI OMAP 353x) 平台
- 額外啟動 gcc 的 Auto-vectorization 優化策略
- 以 ARM NEON 指令集優化 SBC 的執行效能
至於 ARM NEON 指令集,這裡不贅述,可參考 ARM 官方文獻 NEON Technology。 read on# ./prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-objdump -d \
out/target/product/generic/obj/STATIC_LIBRARIES/libjpeg_intermediates/jdmerge.o | egrep "v[add|mov]"
1d4: f2c09012 vmov.i32 d25, #2 ; 0x00000002
1d8: f3c01210 vmov.i32 d17, #32768 ; 0x00008000
200: f26048a9 vadd.i32 d20, d16, d25
204: f22069b8 vmul.i32 d6, d16, d24
208: f26438a9 vadd.i32 d19, d20, d25
20c: f2266821 vadd.i32 d6, d6, d17
簡報: Power Management from Linux Kernel to Android
上週五 (June 19),Matt 跟我分享 Android 之上 Power Management 的背景概念、實做,以及可改進的方向,而論及 Android 的系統架構設計時,不免得先談談 Linux PM,期待這份簡報對進行系統移植與客製化的同好有助益:
升級 Android 內建 GNU Toolchain 到 gcc 4.4
GNU GCC 4.4 已於 Apr 21, 2009 正式釋出,伴隨眾多改進、修正,與硬體平台改善,詳情可見"GCC 4.4 Release Series Changes, New Features, and Fixes",不過 Android repository 裡頭的 prebuilt GNU Toolchain 仍停留在 gcc-4.2.1 (Release date: Jul 18, 2007),總是有些遺憾,且讓我們動手改變。
EMBINUX™ Lab 提供一份 prebuilt GNU Toolchain for Android,參考其 git 的更動,可建立一套基於 gcc-4.4 與 binutils-2.19.1 的 toolchain,筆者準備打包好的套件: toolchain-arm-eabi-4_4_0.tar.bz2。另外,因為 gcc-4.4 對於 C/C++ 語意更加嚴格,像是應用程式對 va_list 的使用就需要調整,筆者將這些小修改整理為 migrate-gcc44.patch。以下是簡要的升級方式:
重新編譯與建構 Android 即可。需要更動的部份,列出作參考:# cd mydroid
# cd prebuilt/linux-x86/toolchain
# tar jxvf toolchain-arm-eabi-4_4_0.tar.bz2
# cd ../../..
# patch -p1 < migrate-gcc44.patch
read on# diffstat migrate-gcc44.patch
core/combo/linux-arm.mk | 2 +-
dist/sqlite3.h | 2 +-
envsetup.sh | 2 +-
pdk/ndk/samples/sample/Makefile.lib | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
改善 Android 中 memcpy 效能
在 Android 內部實做中,有許多細節涉及大量的 memcpy() 操作,比方說將一塊使用者定義的繪圖區域傳遞給 SurfaceFlinger 管理的過程,由於得先轉換成 texture,再對應為 Surface,之間至少需要三次 memcpy。由於 BeagleBoard (TI OMAP3) 透過 HDMI 輸出 (max: 1280x1024),居中涉及大量的繪圖操作,意味著 memcpy() 頻繁被呼叫著,對整體效能有顯著的影響,於是筆者花了一些時間分析。
Android 的 libc 實做 -- bionic -- 已包含針對 ARMv5 優化過的 memcpy(),詳情可參考 libc/arch-arm/bionic/memcpy.S,而 GNU Toolchain (glibc) 中,其實也有一份針對 ARMv5 優化過的 memcpy() 實做,也利用到 ARMv5 的 data prefetch 指令。既然我們採用 ARMv7 架構的 BeagleBoard,何不使用其引入的 NEON SIMD 加速指令集呢?以下就是在 BeagleBoard 所作的 benchmark:
數據如下:
- glibc-armv5 : 181884276 B/s
- bionic-armv5 : 225881095 B/s
- armv7 : 269294302 B/s
- .fpu neon
- .text
- .global memcpy_neon
- .func memcpy_neon
- memcpy_neon:
- push {r4-r11}
- mov r3, r0
- 1: subs r2, r2, #128
- pld [r1, #64]
- pld [r1, #256]
- pld [r1, #320]
- ldm r1!, {r4-r11}
- vld1.64 {d0-d3}, [r1,:128]!
- vld1.64 {d4-d7}, [r1,:128]!
- vld1.64 {d16-d19}, [r1,:128]!
- stm r3!, {r4-r11}
- vst1.64 {d0-d3}, [r3,:128]!
- vst1.64 {d4-d7}, [r3,:128]!
- vst1.64 {d16-d19}, [r3,:128]!
- bgt 1b
- pop {r4-r11}
- bx lr
- .endfunc
Android Dalvik VM vs. Java VM
Google Android 開發團隊為了技術自主、迴避 Java 商標爭議等考量,建構了嶄新的 Dalvik Virtual Machine,骨子裡頭仍支援 Java 程式語言,但 Dalvik VM 設計稍異於典型 JVM,網路上已有豐富的比較,本文就不贅述,筆者想探討的,則是日本 eFlow 公司最近提出的 'Android™'s Dalvik VM on "Mobile Java"',目標就是讓原本的 Java 執行平台 (主要是 Java ME),得以運作針對 Android Dalvik VM 設計的應用程式。日前該專案已開放原始程式碼,主體依據 GNU GPLv2,以下是相關資訊:
- 新聞稿: eflow Releases First Implementation of Android™'s Dalvik VM on "Mobile Java" as Open Source
- 專案開發主頁: android-dalvik-vm-on-java : Pure Java implementaion of Android's Dalvik virtual machine
- Dalvik Execution file format (.dex)
- Complete Dalvik instruction set
- J2ME CLDC API
- Multi-thread (include synchronized block, wait and notify)
"We believe this implementation will particularly benefit manufacturers currently developing Android-powered devices, with a number of which we are cooperating to port the Dalvik VM to their specific hardware and software architectures. By making this implementation available today as open source, and by accelerating our porting and development efforts, we have the firm intention to make a significant contribution to the broader Android community."這裡無從得知,不過,該專案四月底時,一併將 dalvikvm_benchmark 釋出,伴隨內部的效能分析數據,非常有意思。從裡頭的資料來看,標的硬體平台有兩個:
- Google Dev Phone 1 (528MHz - Qualcomm MSM7201A)
- P905i (500MHz - Panasonic UniPhier 4M + JBlend)
- Google Dev Phone 1 (528MHz - Qualcomm MSM7201A) :: 433
- P905i (500MHz - Panasonic UniPhier 4M + JBlend) :: 1811
Android 上的原生 OpenGL/ES
olv 日前在「一千零一夜之 Android Binder」一文提及:
surface manager 可以準備一塊 surface,把 surface 的 fd (一塊 ashmem 記憶體) 傳給一個 app,讓 app 可以在上面作畫。有了這層理解,我們對 android 可以有更自由的發揮,例如,可以不改一行 cairo 的程式碼,就利用 cairo 與 c++ 寫出一個會動的時鐘而 Surface manager 顧名思義,就是管理邏輯上眾多的 surface,其底層對應於 OpenGL|ES 的實做。透過 surface 的處理,我們可讓像 fdclock 這樣原生 (native) 的 C 語言程式,透過同樣在 GNU/Linux 上原生的 Cairo 函式庫,無痛的顯示處理。這實在很吸引人,畢竟若能在 Android 平台充分重用 GNU/Linux 既有的軟體功能,會是多麼有趣的事。且讓我們思考是否能在 Android 上撰寫 C 語言的 OpenGL/ES 應用程式。
Android 已提供初步的 OpenGL/ES 封裝,實做則是透過 agl (Android OpenGL) 底層的 PixelFlinger 與 GPU。關於 Java 部份的 OpenGL APIs 操作,可參閱原始程式碼 frameworks/base/opengl/java/android/opengl/GLSurfaceView.java ,不過現在只看 C 程式的部份。動態連結函式庫必須連結到以下三者:
- libEGL : OpenGL/ES APIs
- libGLESv1_CM : Reference implementation
- libui : Android UI framework (native)
$ . build/envsetup.sh參考的螢幕顯示如下:
$ cd angeles-test/
$ mm
make: Entering directory `/home/jserv/Myth/mydroid'
target arm C: angeles-test <= /home/jserv/Myth/mydroid/angeles-test/demo.c
...

不過,在模擬器顯示的狀況會比實體遜色頗多,可見到相當嚴重的重繪動作,但基本上是可用的。 read on
