«深入淺出 – 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

Render Script 小檔案

因為 Render Script 的重要性似乎比我原先想像地還要厲害, 故整理 Render Script 的用法如下. 主要參考 Google 的文件 [註1].

1. Off line Compile:

以 llvm-rs-cc compile 一個 render script (rs) 檔案, 產生 bit code (bc) 檔案, 例如底下的 foo.bc. 如果不是編成 bit code, 也可以和其他的 Java 檔編成 .Java. 這個過程可以使用 Java Reflection 的概念.

Java Reflection 能夠分析未知的 class, 把新 class 裡面的 name of the constructors, declared fields 和 methods 都抓出來. 換言之, 我們原先所寫的 .rs 檔透過 Java Reflection 取得正確的 Java API 資訊, 產生確實可用的 Java code. 而不會在 run time 才發生錯誤. 包括 Python 也是這類的 script, 而 C# 也支援 reflection, 但 C++ 沒有這個觀念. 

2.  On Line JIT Flow

等到 .bc 檔和 Java 檔都準備好之後, .bc 檔進入到 Android 所支持的 libbcc, 而 Java code 進入到 Android 的 Dalvik JIT, 跑在 DVM 上. 由下圖可以看得出來, 只有 .bc 可以用 GPU 或 DSP 來執行, 而 Java 不能. 這就是 render script 大有前途的地方.

特別值得提的是 llvm-rs-cc 會做很多大量的優化, 以便產生可移植的 .bc 檔. 而 libbcc 就是一個輕量級的 compiler, 目標只是針對本地平台已知的特性優化.

上次提到 HoneyComb 首先釋出 rs 的 API, 此時它還沒有用到平行處理. 在 ICS 版, 有個 rsForEach() 把每個 reflected Java helper 都叫起來.

RS 的範例如下:

從參數我們可以得知, 它在計算 luminance = 0.299 red + 0.587 green + 0.114 blue, 不愧是 C99 like.

[註 1] http://llvm.org/devmtg/2011-11/Hines_AndroidRenderscript.pdf

 

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 能做到什麼程度, 我沒有報什麼期望.

好用的 Outlook 整理工具

因為屢次 sync 通訊錄的關係, 我在 Outlook 裡面的行事曆或是通訊錄變成有好多重複的備份. 這種東西雖然害處不是很大, 但是既浪費硬碟空間, 看了也礙眼.

如果按照 Microsoft 官網上推薦的方法, 是可以一筆一筆地刪掉. 不過正常人應該都不會這麼做.

幸好, 還是有聰明的免費工具可以選擇. 我找到一個 VAitA 出品的 Outlook Duplicate Item Remover.  安裝它之後, 它在 Outlook 裡面會產生一個 ODIR 的按鍵. 點選此鍵, 會跳出一個應用程式, 我們就用它刪除各種重複的項目, 包括行事曆, 信件, 聯絡人, 工作, 筆記等等.

比較遺憾的是它只有 Windows 版本, 所以得在 Microsoft Windows 的環境下把東西清乾淨, 再靠 exchange server 更新到 Mac 的 Outlook 上. 另外一個限制是 64 bits 的 Office 不適用此軟體.