How to get recovery.img?

大部分的 Android 手機可以透過 dd 把 recovery partition dump 出來,比如 PadFone S 可以使用

dd if=/dev/block/platform/msm_sdcc.1/by-name/recovery of=/sdcard/recovery.img

取得 recovery.img。

但像 ZenFone 這種放在隱藏 partition 的該怎麼提取呢?其實可以透過 OTA package 或者原廠 ROM 的幾個檔案還原。

一般來說 recovery.img 不一定會完整包含在 OTA package,因為他的內容與 boot.img 相似,通常只差幾個小檔案,所以廠商大多透過 patch 的方式在升級後寫入新的 recovery。我們可以從 OTA package (或者 ROM) 裡面找到 boot.imgrecovery/etc/install-recovery.shrecovery/recovery-from-boot.p,這幾個便是主要產生 recovery 的檔案,透過對 boot.img 的 patch 可以讓 OTA package 省去不少空間。那我們要如何從這兩個檔案與 boot.img 還原 recovery.img 呢?Android 提供了一個工具叫 applypatch,參數如下:

applypatch     

origin_image_name 就是準備拿來 patch 的基礎檔案 boot.img,target_image_name 自然是我們想要的 recovery.img,而 target_image_sha1 為 recovery 的 SHA1 值,target_image_size 為 recovery 的大小 (bytes),patch_image_name 即是 recovery-from-boot.p 這份修補檔,而 patch_sha1 就是修補檔的 SHA1 值。而這些數值其實都可以在 install-recovery.sh 裡面找到,以 ZenFone 5 1.17.40.16 WW 版為例:

#!/system/bin/sh
update_recovery --check-sha1 0d46024fcdba65dc82ca5fb568eccf36885de815 \
                --src-sha1 d8d2bbfd8dd3eaa648073876a229ac030ebdc802 \
                --tgt-sha1 7cf95a376c8d8b0f47a9bd9062851161fac657d2 \
                --tgt-size 11332608 \
                --patch /system/recovery-from-boot.p

其中 tgt-sha1 為 recovery.img 的 SHA1,tgt-size 為 recovery.img 的大小,而 src-sha1 為 recovery-from-boot.p 的 SHA1,因此我們可以得到產生 ZenFone 5 1.17.40.16 WW 版的 recovery 命令為:

applypatch boot.img recovery.img 7cf95a376c8d8b0f47a9bd9062851161fac657d2 11332608 d8d2bbfd8dd3eaa648073876a229ac030ebdc802:recovery-from-boot.p

所以如果我們把 boot.img,recovery-from-boot.p 放在同個目錄下,那麼我們可以把手機接上,輸入下面的指令取得 recovery.img:

adb push boot.img /data/local/tmp
adb push recovery-from-boot.p /data/local/tmp
adb shell 'cd /data/local/tmp; applypatch boot.img recovery.img 7cf95a376c8d8b0f47a9bd9062851161fac657d2 11332608 d8d2bbfd8dd3eaa648073876a229ac030ebdc802:recovery-from-boot.p'
adb pull /data/local/tmp/recovery.img

至於拿出 recovery.img 可以幹嘛?切換不同區域的 ROM 或者在某些緊急狀況下可以還原原廠的 ROM。

CWM Recovery for ZenFone 5 (POC)

警告:這篇是給 DEV 參考用,如果沒有相關基礎知識,使用後手機無法開機,本人不會幫忙解決。
雖然說手機尚未 unlock,隱藏的 partition 也無法透過 dd 寫入,但很久以前用過 Xperia Mini Pro 也是類似的狀況,但 XDA 的大神們還是想辦法搞了個 CWM recovery,理論上 ZenFone 也可以透過同樣的方式使用 CWM Recovery,所以花了點時間做個 POC (Prove of concept)。

檔案在這:zenfone_5_cwm_installer.zip,另外有 zenfone_5_cwm_update.zip,可以在刷入原廠 ROM 之後再把這個 POC 刷回去,或者參考打包用。原始檔案我都放在 github:https://github.com/shakalaca/zenfone_5_cwm

先決條件:
- 手機有 root
- 電腦有裝 adb
安裝方式:
- 解開 zenfone_5_cwm_installer.zip
- 執行 install.bat
使用方式:
- 開機時注意手機上面的指示燈,當紅燈亮起時,按一下音量大或小,沒意外就可以看到 CWM recovery 的選單了
- 目前使用的版本為 6.0.2.8,這是從 Samsung Galaxy Tab 3 (P5210) 的 CWM Recovery 抓來的版本
操作上會有點 lag,太大的檔案也無法 apply,不過因為是 POC 也就不用太強求了,有興趣的可以想想看怎麼讓它變得可用。:)

TWRP recovery 2.7.1.1 for PadFone S

檔案在這:asus_t00n_twrp_2_7_1_1.img
手機得先 root,在 shell 把映像檔寫入

dd if=asus_t00n_twrp_2_7_1_1.img of=/dev/block/platform/msm_sdcc.1/by-name/recovery

接著重開至 recovery,重開機後,當 ASUS logo 消失時等 60 秒左右,再按一下 power 按鈕,就可以看到 TWRP 選單囉。我目前還沒有驗證所有功能,有空再來試試看,請有興趣的記得先備份好手機資料。

Parameters for packing boot.img for PadFone S

筆記一下,這邊是直接拆開原始的 recovery.img 後修改 ramdisk 再打包:
$MKBOOTIMG --base 0 \
--kernel recovery.img-zImage \
--ramdisk recovery.img-ramdisk.gz \
--cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x37 ehci-hcd.park=3 UNLOCKED=Y’ \
--pagesize 2048 \
--ramdisk_offset 0x02500000 \
--dt recovery.img-dt \
-o new-recovery.img
cmdline 後面的 UNLOCKED=Y 加上去後再配合 default.prop 塞 service.adb.root=1 才可以讓 adb shell 進去時為 root 權限。

[Root] Downgrade ZenFone from 1.15.40.35_20140715

2014-07-20 Update: 補上 fastboot 步驟,抱歉少了這一步是無法修改 recovery 的 ^^
這一版的升級做了一個不算小的修改:在 recovery 的 default.prop 將 ro.build.date.utc 的數值調小:

ro.build.date.utc=12684704

這樣的修改會導致手機無法降版,因為目前官網上抓下來的 ROM file 裡面的 script 最前面這麼寫:

assert(greater_than_int(getprop("ro.build.date.utc"), 1392739200));

雖然應該沒多少人喜歡換版本,但這邊還是筆記一下退版的方法,root 限定。又因為這樣的退版如果沒處理好可能導致之後無法升級軟體版本,我就只講方法不做懶人包了。:P
- 下載舊版 (比如 1.14.40.50) 的 ROM file,解開後在 recovery 目錄下找到 boot.img,recovery-from-boot.p 與 etc/install-recovery.sh
- 透過 fastboot 刷入 boot.img (fastboot flash boot boot.img)
- 修改 install-recovery.sh,把 /system/recovery-from-boot.p 換成 /data/local/tmp/recovery-from-boot.p
- 將這兩個檔案透過 adb push 到 /data/local/tmp
- 進去手機以 root 執行 install-recovery.sh

接著就可以依照原先的方式降版了。

Enable Chromecast screen mirroring feature on your device

這次就不包懶人 app 了,需要 root,主要的邏輯在 enabler.sh,基本上沒啥傷害 (?)

先抓 sqlite3 binary for Android
再抓從電腦執行的前導程式 go.bat,裡面只有 adb command 而已。
最後是主要啟用的腳本檔 enabler.sh,裡面做的事情很簡單:修改 Play Service 的 database 開啟使用 Chromecast Screen Mirroring 的旗標。

所以東西都抓下來後,執行 go.bat 就好了。聽說有些 Samsung 的機器不能跑,不過我手上也就這麼多台手機,有 Chromecast 但手上的裝置不再官方支援列表的就自行參考看看吧。

Reference: http://forum.xda-developers.com/showthread.php?t=2730422

Use versionName & versionCode from AndroidManifest.xml in gradle

與別人合作的 project 因為對方用的是 Eclipse (其實是只有我用 Android Studio),版本的設定會習慣放在 AndroidManifest.xml 裡面,但這麼一來如果 gradle 運行中需要使用到 versionName 或者 versionCode,就得額外設定並且注意是否與 AndroidManifest.xml 同步。這麼做除了讓專案的維護更麻煩以外,還得注意不同步的問題。
最早都是透過複雜的 script 分析 AndroidManifest.xml 把設定值取出,後來發現有個很好用的工具:com.android.builder.core.DefaultManifestParser。
在你的 build.gradle 中最前面先

import com.android.builder.core.DefaultManifestParser

接著在 defaultConfig 裡面設定:
````
defaultConfig {
def manifestParser = new DefaultManifestParser()
versionName = manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)
versionCode = manifestParser.getVersionCode(android.sourceSets.main.manifest.srcFile)
}

```
That’s it ! 唯一要注意的是,sourceSets 的設定要放在 defaultConfig 之前,否則 gradle 會跟你抱怨 manifest 找不到。

Handling signingConfigs with gradle

之前都是透過 gradle.properties 分開管理 release 用的簽章,好處是不用把敏感的 information 也丟到公開的 repo,但有個問題最近困擾著我:如果存放 keystore 的路徑有中文,gradle 在 sign apk 時無法正確讀取 keystore。
試過很多亂七八糟的方法,最後是透過分開的 .gradle 檔案滿足這樣的需求。
首先建立 signing.gradle,裡面很精簡的只設定 release 用的 signingConfig:

android {
    signingConfigs {
        release {
            keyAlias 'YourKeyAlias'
            storeFile file('YourStoreFile')
            storePassword 'YourStorePassword'
            keyPassword 'YourKeyPassword'
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

而在 gradle.properties 指定一個 property 存放 signing.gradle 的路徑:

releaseSignConfig=/path/to/signing.gradle

最後在主要 project 的 build.gradle 中判斷是否需要引入:

if (project.hasProperty(“releaseSignConfig") && new File(project.property(“releaseSignConfig")).exists()) {
    apply from: project.property(“releaseSignConfig");
}

或者你也可以寫:


if (project.hasProperty(“releaseSignConfig") && new File(releaseSignConfig).exists()) {
    apply from: releaseSignConfig;
}

這樣便可以解決中文或者空白路徑的問題 如果各位先進有更好的解法 也歡迎來討論

[Root] SOP when failed to apply OTA update

之前發在 Mobile01,轉回來做個記錄..
不少網友 OTA 更新失敗都是因為 Root 後就把系統檔案修改或者刪除,這邊提供一個標準還原流程。(因為已經被問到爛了)
下載符合手機版本的原廠 ROM
ZenFone 5 請到這邊找 http://www.asus.com/tw/Phones/ASUS_ZenFone_5/HelpDesk/
ZenFone 6 請到這邊找 http://www.asus.com/tw/Phones/ASUS_ZenFone_6/HelpDesk/
從 驅動程式及工具程式 進去, 選 Android 就可以看到一堆列表.
解開下載的檔案,會得到格式如下的壓縮檔:

UL-ASUS_T00?-$$-#.##.##.#-user.zip

如果手機是 ZenFone 5,? 為 F 或 J;如果手機是 ZenFone 6,? 為 G。
$$ 代表區域,可能是 TW (台灣版),CHT (中華客製版),CN (中國版)或 WW (全球版),注意要跟手機的版本一樣。
而 #.##.##.# 為版號,也要跟手機的版本一致。
把剛剛下載回來的檔案,版號的部分 (#.##.##.#) 改為 10000,所以會產生類似 UL-ASUS_T00F-TW-10000-user.zip 這樣的檔案名稱。
手機透過 usb 傳輸線連接到電腦,在檔案總管可以找到 ZenFone 的內部儲存空間,把檔案丟進去。
傳輸完畢,先 unroot。
拔開傳輸線以後,會出現升級提示,確認手機電力充足,按確定即可重置作業系統,這個動作不會清除手機資料。
* 還原完畢,root 後等 OTA 更新出來,按保留 root 接著套用更新。如果安裝新版的 Root ZenFone 直接啟用 OTA 生存模式,再套用更新即可。
然後再一次呼籲,root 後不喜歡的內建軟體可以停用,但不要刪除否則 OTA 更新一定會失敗。至於什麼 Lucky patcher 會改到 framework 的鬼東東,除非你意識清楚否則 OTA 更新一定會失敗。

[Root] RootZenFone 1.3r

一直想更新很久了, 但無奈手邊事情太多, 再加上有些功能考慮要獨立出來做, 所以程式碼寫了又砍砍了又寫.. 最後決定只先加入最重要的功能: OTA 生存模式.
連結在這: http://goo.gl/YuqeGH (Dropbox)
分流在這: http://goo.gl/oCIGN0 (Mega)
已經 root 的朋友安裝後直接點 "啟用 ROOT 生存模式 (升級後自動保留 ROOT)", 還沒 root 的朋友這一版在 root 後會自動啟用該功能.


因為這是個會修改系統檔案的 hack, 所以如果之後 OTA 更新失敗, 請依照下面的 SOP 進行:
0. 先確定還有收到 OTA 更新通知.
1. 開啟 RootZenFone, 解除 ROOT 生存模式 (將修改過的系統檔案還原)
2. 狂點 “ 已經 root 囉 :) “ 就會出現舊的 “ 升級後保留 ROOT “ 按鈕

3. 點選 “ 升級後保留 ROOT “
4. 套用 OTA 更新
5. 快樂更新系統, 並留言給我更新軟體 :p