HW Overlay 小檔案

看到這個題目在 wiki 只有英文和韓文, 忍不住想寫一個中文的精簡版. 不過寫著寫著就偏離主題, 變成了 Android 為何不全面支持 HW Overlay?

我們在 Windows 螢幕上看到的畫面, 基本上是由視窗疊加而成的, 前景擋住後景, 就成了我們看到的模樣. 在其他有視訊輸出的產品中, 同樣會有物件互相遮蔽的現象, 例如: 字幕浮現在電影上, 這樣就是兩個個物件. 如果再加上進度條 (progress bar), 就變成 3 個物件. 當繪圖系統需要依序畫出這三個物件時, 可以用軟體去檢查前後順序, 只把需要的部份畫出. 在 Android 系統中, Surface Flinger 就在做這件事 [註1].

既然有軟體的解法, 硬體解法會不會更快更有效率呢?是的, HW overlay 就是這個硬體的解法. 當每個物件都畫在自己的記憶體, 最後再依據每個物件的先後順序和透明度 (alpha blending) 一次疊加, 那麼每個物件就不用等來等去, 只要各畫各的就好. 如此一來, 雖然浪費了好幾塊記憶體, 控制卻變得很簡單. 特別是物件的更新速率差異很大時, 互等會導致大量浪費頻寬 – 例如電影 (30~60Hz) 與字幕 (大約 0.2~0.5 Hz).

Surface Flinger HW Overlay

上面這張圖有個小問題, 就是把 SurfaceFlinger 和 Overlay 畫成兩個獨立的模組. 實際上, 在 Android 中, HW Overlay 和 Surface Flinger 關係密切. HW Overlay 算是 SurfaceFlinger 的一個特例 [註 2]. 請參考下圖.

現在的 IC 幾乎都有 HW overlay 的能力, 應該沒甚麼好討論的, 可惜故事還沒有完. 大家如果把玩手上的 Android 手機或是平板, 可能會在設定裡面看到 “停用硬體重疊圖層" 這個選項. 既然 HW overlay 看起來比較好, 幹嘛把它停用呢? 每一個 OpenGL 的 process 都需要 2~8MB 的 RAM, 浪費記憶體就不用說了. GPU 還要挺高檔才行 [註 3].

每秒可以畫 1000 M pixel/second 的 200MHz SGX544, 在 1920×1080@60FPS (frame per second) 的輸出螢幕上, 能在每個 pixel render 8.0375 次. 若是換成了 SGX531就只能 render 4 次 [註 4]. 這  4 次如果用來畫一層背景, 一層電影. 一層進度條和 OSD (on screen display), 一層字幕, 就已經達到 GPU 的硬體極限. 此時只是做到 HW overlay 的水準而已, 但什麼 3D 動畫效果都畫不出來了.

以上都是說 Android 的壞話, 但 Google 卻可以藉著不支援 HW Overlay 來統一硬體的差異, copybit 不就在 Android 4.0 上被拔掉了嗎? 若是放任每一家廠商製作的 HW Overlay 都不相同, 當然就限制了 APP (跨平台的) 的互通性. 再者, GPU 只要聰明地用, 不要常常 redraw 沒用的畫面, 效率還是不會太差 [註 3]. 按照 Android 的官方說法, 全部的畫面都能進入 GPU 的話, 使用者將可以得到更多樂趣! 至於 GPU 的計算能力….當然必須夠, 這不是 Android 的責任範圍, 它只是個做軟體的. [註5]

Media effects for transforming images and video

A set of high-performance transformation filters let developers apply rich effects to any image passed as an OpenGL ES 2.0 texture. Developers can adjust color levels and brightness, change backgrounds, sharpen, crop, rotate, add lens distortion, and apply other effects. The transformations are processed by the GPU, so they are fast enough for processing image frames loaded from disk, camera, or video stream.

[註]

1.  Android Display (surfaceflinger and Overlay)

2. Android 显示系统

3. The truth about hardware acceleration on Android

4. PowerVR

5. Ice Cream Sandwich

«深入淺出 – Android 系統移植與開發測試» 的補充

這本書的發行的時候, Android 的版本只是 2.2. 現在 Android 已經到 4.2 版了, 所以有些內容需要修改. 我把需要改變的地方整理如下:

0. 首先要安裝 64 bit 的 ubuntu

如果沒有光碟機, 會有點小麻煩. 因為 ubuntu 的 Windows installer 預設是安裝 32 bit 版本. 所以要先下載 64 bit (amd64) 版, 然後手動選取 iso 檔.

如果一定要用 ubuntu 32 bit 版本, 請參考這一篇 [註 0].

1. 在 ubuntu 上安裝以下的套件, 修改的地方用紅色, 並新增第四行.

sudo apt-get install git-core flex bison gperf libesd0-dev zip

sudo apt-get install libwxgtk2.8-dev zlib1g-dev build-essential libstdc++5

sudo apt-get install tofrodos  x-dev libx11-dev lib32ncurses5-dev xsltproc

sudo apt-get install gcc-multilib g++-multilib libc6-dev-i386 ia32-libs x11proto-core-dev lib32readline-gplv2-dev lib32z1-dev [註 1]

如果 apt-get 失敗, 請參考這篇 “回覆: 最近在安裝新的10.10無法更新


接下來就是 Java 了, 基本上 Java 套件會找不到. 所以要先讓 ubuntu 可以安裝過期軟體 [註 2].

apt-add-repository “deb http://old-releases.ubuntu.com/ubuntu/ jaunty multiverse"
apt-add-repository “deb http://old-releases.ubuntu.com/ubuntu/ jaunty-updates multiverse"

此時在 /etc/apt/sources.list 的最後四行會看到:

deb http://old-releases.ubuntu.com/ubuntu/ jaunty multiverse
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty multiverse
deb http://old-releases.ubuntu.com/ubuntu/ jaunty-updates multiverse
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty-updates multiverse

接著就可以更新 source list.

sudo apt-get update

sudo apt-get install sun-java6-jdk


再來就可以安裝 repo.

cd ~/bin

curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo

chmod a+x ~/bin/repo

PATH=~/bin:$PATH


再來取得 Android source code.

repo init -u https://android.googlesource.com/platform/manifest.git

repo sync

經過了不知道多久….

接著做設定

lunch

畫面出現

You’re building on Linux

Lunch menu… pick a combo:
     1. full-eng
     2. full_x86-eng
     3. vbox_x86-eng
     4. full_mips-eng
     5. full_grouper-userdebug
     6. full_tilapia-userdebug
     7. mini_armv7a_neon-userdebug
     8. mini_armv7a-userdebug
     9. mini_mips-userdebug
     10. mini_x86-userdebug
     11. full_phantasm-userdebug
     12. full_mako-userdebug
     13. full_maguro-userdebug
     14. full_manta-userdebug
     15. full_toroplus-userdebug
     16. full_toro-userdebug
     17. full_panda-userdebug

Which would you like? [full-eng]

預設就是第一項 full-eng.

make

如果 64 bits 編譯工具沒弄好, 可能看到錯誤訊息:

prebuilts/tools/gcc-sdk/gcc: line 40: prebuilts/tools/gcc-sdk/../../gcc/linux-x86/host/i686-linux-glibc2.7-4.6/bin/i686-linux-gcc:

用了這招可以修好 [註 3]

cd prebuilts/tools ; git reset –hard HEAD^
cd external/qemu ; git reset –hard d4f5a3ae87a7246613188940c1667bf2880da402

如果看到

/bin/bash: prebuilt/linux-x86/sdl/bin/sdl-config: No such file or directory
/bin/bash: prebuilt/linux-x86/sdl/bin/
sdl-config: No such file or directory

可能是 repo init 時設錯. 我發現我是設錯 username, 此時用

repo init –config-name 重設一次 username 和 email address


錦上添花的設定:

1. 減少不必要的編譯.

export USE_CCACHE=1

2. 設定 USB 設備:

sudo vim /etc/udev/rules.d/51-android.rules
加入設定指令, 讓 Android user 可以直接使用 USB 設備, 忽略到 OWNER 就變成是 root 才能訪問.

# adb protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1″, ATTR{idProduct}=="4e12″, MODE="0600″, OWNER="<username>"
# fastboot protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4″, ATTR{idProduct}=="0fff", MODE="0600″, OWNER="<username>"
# adb protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1″, ATTR{idProduct}=="4e22″, MODE="0600″, OWNER="<username>"
# fastboot protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1″, ATTR{idProduct}=="4e20″, MODE="0600″, OWNER="<username>"
# adb protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="22b8″, ATTR{idProduct}=="70a9″, MODE="0600″, OWNER="<username>"
# fastboot protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1″, ATTR{idProduct}=="708c", MODE="0600″, OWNER="<username>"
# adb protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8″, ATTR{idProduct}=="6860″, MODE="0600″, OWNER="<username>"
# fastboot protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1″, ATTR{idProduct}=="4e30″, MODE="0600″, OWNER="<username>"
# adb protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451″, ATTR{idProduct}=="d101″, MODE="0600″, OWNER="<username>"
# fastboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451″, ATTR{idProduct}=="d022″, MODE="0600″, OWNER="<username>"
# usbboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451″, ATTR{idProduct}=="d010″, MODE="0600″, OWNER="<username>"

sudo chmod a+rx /etc/udev/rules.d/51-android.rules


[註 0] ubuntu 11.10(32位系统)下编译android源码

[註 1] Ubuntu 64 bit 编译 Android

[註 2] ubuntu安裝sun-java5-jdk

[註 3] wrappers for 32/64-bit using wrong path?

[註 4] [Linux]ubuntu 11.04(64 bit)抓取android4.0.4原始碼跟編譯source code/SDK/kernel

Bitcode 與 Bytecode

大家都知道 Android 裡面有 Java virtual machine (JVM), 而 JVM 上面執行的就是 Java 的 byte code. Byte code 具有跨平台的性質, 所以 Java 可以 compile once, execute everywhere. 但 Android 裡面還有一個 bit code 就太為人所知.

Bit code 的功能和 byte code 一樣, 但是它不僅限於 Java 語言. 根據伊利諾大學的 LLVM (Low Level Virtual Machine) 計畫, front end 的 compiler 可以是 GCC, 而支援的語言包括 Ada, C, C++, D, Fortran, 和 Objective-C 等等. 這些高階語言被編成 LLVM IF (intermediate form), 然後被放在 virtual machine 上執行. 當然, 從 IF 也可以直接再編成可執行檔.

LLVM 的官網似乎都是用 LLVM IR (intermediate representation) 來代替 IF (WIKI 用語) 一詞, 而這個 LLVM Bitcode File Format 在他們的官網就可以找得到. 

Bit code 除了跨平台之外, 還有什麼好處呢?Google 在推的 RenderScript Compute 就是其中一個應用.  使用者可以先寫好 script, 然後交給 LLVM compiler 去翻譯成對平台最有利的 binary. 比方說這個平台的 GPU (Graphic processor unit) 很弱, 那麼某些 code 在 just in time compile 的時候就會讓 CPU 多分擔一點工作. 從 Android 3.0 的 Honeycomb 開始就支援 LLVM compiler 的 API, 放在 /system/lib/libbcc.so.

Android 即將進入 K 版

Android 一向以英文字母順序來命名產品, 大家可能都注意到它是甜點名稱, 而忽略掉它在 10/29  (傳言有誤, 待更新)就要進入第 K (11th) 版了. Android 進版如此迅速, 當然反映出它跟進競爭對手的決心. 否則它大可以讓使用者覺得 4.0, 4.1, 4.2 都是第四版, 而毋須給予各自的暱稱. 不過對於軟體開發的工程師而言, 實在是追得太辛苦了. 網路有個很好的比較表, 可以知道每一版的 Android 有何差異.

[打岔 1] 據說第 K 版的名稱是酸橙派 (Key lime Pie), 那麼第 P 版來個珍珠奶茶 (Perl milk tea) 也不算是意外.

我這邊另外做一張表, 把三個作業系統 (假如 Android + Linux 也算一個 OS) 的三個重要指標 – 能否跨平台, 人機互動, 消滅異己的版號列出來. 至於雲端, Market, 社群, 開機速度, 拍照, 強化語音辨識, 改善 UI 速度或美化等等不具戰略價值或大家都有的功能, 我就自動忽略了.

  Google Apple Microsoft
消滅異己 JB, 去 FLASH

IOS6, 去 Google 化
向來不支援 FLASH

不知
人機互動 JB (2012/6/27), Google Now IOS5, SIRI Win8, 據說有  chatter
跨平台

ICS (2011/10/19)

IOS5 (2011/10/12) Win8 (2012/10/23)

[紅色為更正]

不用說, Microsoft 真是敗在 Windows 太過臃腫. 以致於在跨平台上輸了競爭對手好大一截, 不過它也並非全無優勢. Skype 和 XBOX 算是它的獨門武器. 預計另外兩大陣營短期之內, 都不可能跟上進度. Apple 看似占盡上風, 不過封閉系統的問題也慢慢浮現 – 一個遊戲 App 就要 60MB,你手中的蘋果裝置塞爆了嗎?.

在人機互動方面, 只要耕耘得夠深, 客戶很容易養成習慣. 如果我是它們的操盤手, 我一定要讓這些裝置的 AI 軟體變成主角, 而不是綁定硬體. 它們需要被取名字, 而且能夠跨平台轉生. 如此一來, 客戶未來在換機時, 不得不考慮到讓那個 "虛擬的朋友 – 人工智慧" 還能繼續投胎轉世. 如果客戶再也不買我家的硬體產品, 沒關係, 只要付一點投胎費, 虛擬朋友在別的平台也可以活過來, 只是難免會有一點相容性的問題而已.

[打岔 2] 如果 AI 太強, 會不會主動拗客戶幫它 "換屋" 啊? "主人, 我想搬到最新的 iphone8…, 聽我朋友說隔壁老王的新手機很好住…"

最後, 有篇 Win8 十大升級理由 供大家參考. 其中 style app – 預設style App整合Facebook、Flicker、Google、Twitter、LinkedIn服務。個人覺得這類功能挺重要的. 畢竟我們沒有那麼多時間去關注那麼網站, 還是讓他們自己協調一下匯報上來就好! 有 AI 當然就更好. 但 Windows 能做到什麼程度, 我沒有報什麼期望.

Galaxy Note 也升級 Android 4.0 了

某天早上打開 Kies 的視窗時, 赫然發現 Note 已經有新的韌體可以升級了. 點進去一看, 果然是Android 4.0. 我一時手癢, 就叫 Kies 幫我安裝. 結果這個安裝時間大概有 50 分鐘左右, 又不能拔線, 害我上班差點遲到.

新的手機長相和原來差不多, 倒是把我原來排好的 widget 全部改為預設值, 等於我先前白忙了一場. 完整的升級 “開箱文" 請參考這一篇: 三星Galaxy Note終於可以升上Android 4.0版了,趕快來升級吧!

升了 4.0 之後, 當然我最關心的是多了什麼好東西?最大的發現有兩個:

首先就是 “臉解鎖" 不太好用. 在燈光充足的狀況下, 辨識率還算 OK, 畢竟我一天之內也不會變太多. 不過到了光線暗的地方就不行了, 一句 “找不到臉孔" 或是 “抱歉!不認識你.",  就得 key in PIN 或是畫綠色矩陣上的圖形解鎖.

為了增加辨識率, Android 的設定 → 安全性裡面有一個改善臉辨識的選項, 每重新訓練一次, 就要再輸入一次 PIN, 其實真是有點煩. 難道就不能來個 “訓練 10 連拍", 讓我有機會把表情做足, 或每付眼鏡都換一次嗎?這裡還有很多改進空間, 目前只能算是噱頭.

第二個重點就是: 設定 / 儲存空間 / 裝置記憶體 / 總空間變成 1.97GB 了. 我記得它的規格就是 1GB, 以前看也是 1GB, 升級後竟然變成 2GB 了. 而這 2GB 已經用掉了 1.5GB, 也就是我還是只剩下 516 MB 可以用. 所以我猜這是 bug 吧!