⚠️ 注意:本人非專業 Android 開發者,本文僅參考,如有錯誤,歡迎指正!
⚠️ 注意:本人非專業 Android 開發者,本文僅參考,如有錯誤,歡迎指正!
⚠️ 注意:本人非專業 Android 開發者,本文僅參考,如有錯誤,歡迎指正!
本文章以適配小米 10S 為例, 小米 10S 為 VAB 設備, 不相容 GKI, VNDK 版本 30。
編譯伺服器系統: Ubuntu 22.04
Prebuilt Vendor, 顧名思義, 預編譯 Vendor。指的是使用廠商已經編譯好的 Vendor 進行 Custom 適配。這樣可以大大降低適配難度, 減少適配 debug 時間。
Google 在 Android 8.0 引入了 PT(Project Treble), 這使得 Android Custom ROM 的適配和 debug 難度大大降低。再加上今年 Google 再次引入 GRF(Google Requirements Freeze) aka Vendor Freeze, 這使得適配難度再次降低。
在 Android 8.0 之前, 要適配 Custom ROM, 需要通過 AOSP, CAF 或其它晶片組, 硬體廠商開源的原始碼編譯設備硬體所需要的函式庫, HAL 或驅動, 且每次 Android 大版本升級都需要重新編譯, 且極有可能在新版本 Andorid 運行或編譯中出現問題, 需要等待原始碼更新修復或自己手動修復。
在引入 PT, GRF 後, 我們可以直接使用Stock ROM 中的 Vendor, 只需要編譯 Kernel 和 System 即可, 且因為 GRF 的引入, Vendor 至少可以相容 3 個大版本的 Android 更新。(例如小米 12 預裝 Android 12, VNDK 版本 32, 則此版本的 Vendor image 至少可以相容到 Android 15, VNDK 35)
在設備適配初期, 我推薦使用 LineageOS 進行設備的 bring up
我們需要原廠系統中的部分文件來保證部分功能的正常使用, 例如 IMS, 所以我們需要先解包原廠系統
因為是 prebuilt vendor, 所以我們需要從原廠系統中提取出 vendor, odm image
然後將 images 目錄下的 vendor.img 和 odm.img 複製到 device/xiaomi/thyme-prebuilt/
下
因為是適配初期我們使用 prebuilt kernel 簡化適配流程
然後將解出來的 kernel
, dtb
和 dtbo.img
複製到 device/xiaomi/thyme-prebuilt/
下
我們需要先初始化 device tree, 然後編譯 recovery, 來驗證 kernel 的可用性
這是 Android make 編譯系統中的編譯配置文件, Android 編譯系統會 include 原始碼目錄下的所有 Android.mk 文件, 包括設備資料夾中的 Android.mk
我們需要在這個文件 include 當前資料夾下的所有 makefile 文件, 否則 Android 編譯系統不會去 include 設備資料夾中的其它 makefile 文件。
這是 Android 引入 soong 編譯系統後的編譯配置文件, Android 編譯系統會 include 原始碼目錄下的所有 Android.bp 文件, 包括設備資料夾中的 Android.bp
目前我們不需要編譯外部的 soong 模組, 因此直接創建一個空的 Android.bp 文件即可
這是用於定義設備編譯配置的地方, 我們可以在這裡定義多個設備配置用於編譯多個設備或同設備的變種版本
這是我們的設備編譯配置文件, 我們需要在這裡定義設備的基本訊息, 以及設備的編譯配置。
這是設備的板級配置文件, 我們需要在這裡定義設備的硬體配置。
這是設備的編譯配置文件, 在這裡面可以 include 其它編譯配置文件, 也可以指定要編譯的模組, 功能類同 lineage_thyme.mk。
這是 fstab 文件, 用於指定分區的掛載點, 以及掛載點的屬性, 例如是否可讀寫等。
必須要有這個文件, 否則 Linux Kernel 會無法掛載所需的分區, 導致 Android 或 Recovery 無法啟動
這個文件可以在 vendor 分區中被找到, 具體可以使用此命令尋找
找到後 copy 到設備資料夾中的 rootdir/etc/ 目錄下
然後我們可以在 device.mk 中使用 PRODUCT_COPY_FILES 複製到 ramdisk 或者 vendor ramdisk 中, 例
也可以在 rootdir 目錄中新建 Android.mk 去定義自訂模組然後在 device.mk 中指定編譯, 例
完成上述步驟後我們便可以開始編譯 recovery 來測試了
編譯完成後刷入設備
如果設備可以正常進入編譯後到 recovery 我們便可以進入下一步,否則請參考文章末的 debug 指南進行 debug。
由於這部分內容較多,具體請參考本人 GitHub 倉庫中的提交歷史
此文章僅挑出其中一些重要的部分進行說明
proprietary-files.txt
, extract-files.sh
和 setup-makefiles.sh
這三個文件複製 vendor tree 中的文件建立,改動和提取
如果要建立或修改 vendor tree 中的文件,請務必使用 extract-files.sh 腳本提取建立或修改。
詳情請參考 LineageOS 官方文件:
proprietary-files.txt
該文件屬於一個清單,用於列出需要從原廠系統中提取的文件,以及它們的目標位置。
extract-files.sh
會遍歷這裡面的文件,然後從原廠系統中提取出來,放到 vendor tree 中。
extract-files.sh
該腳本會根據 proprietary-files.txt
中的文件,從原廠系統中提取出來,放到 vendor tree 中,然後調用 setup-makefiles.sh
腳本建立 makefile。
setup-makefiles.sh
該腳本會被 extract-files.sh
調用,用於建立 makefile。
FCM
或 manifest.xml
或 compatibility_matrix.device.xml
這是 HAL 的清單文件,用於指定設備支援的 HAL,以及它們的版本。Android 會根據清單中的 HAL 來載入對應的 HAL。
詳情請參考 AOSP 官方文件:
https://source.android.com/docs/core/architecture/vintf?hl=zh-cn
bootctrl
以及 gpt-utils
或 mtk_plpath_utils
A/B 設備需要這些模組用於進行無損升級,詳情請參考 AOSP 官方文件:
https://source.android.com/docs/core/ota/ab
⚠️ 注意: 高通設備與聯發科設備所使用的 bootctrl 不同
高通設備的 bootctrl 以及 gpt-utils 可以從 CAF 或 CLO 中拿取。
⚠️ 注意: 高通已經在 2022 年 5 月 31 日停止對 CAF 的更新,並決定在 2023 年 5 月 31 日徹底停用,所以建議使用 CLO 中的 bootctrl 和 gpt-utils
聯發科設備的 bootctrl 以及 mtk_plpath_utils 請參考:
如果上面的兩個模組對您的聯發科設備不起作用,請考慮使用 prebuilt 的 bootctrl 和 mtk_plpath_utils。
我們需要編譯部分組建以及從原廠系統提取部分文件來支援 VoLTE。
高通設備參考:
聯發科設備參考:
同時請確保所編譯的 ROM 以及增加了 MTK IMS 的支援,具體可以參考: https://gerrit.pixelexperience.org/q/topic:mtk-ims
Overlay 是個很重要的東西,可以動態的調節一些系統特性,比如說狀態欄的高度,圓角的大小等
部分 Overlay 配置可以從原廠系統中提取,具體路徑在
如果需要自己增加 overlay 可以參考這些連結來檢查哪些 overlay 是可用的,下面列出的是比較常用的:
如果需要找更多的 overlay 可以進入 cs.android.com 尋找相應 app 模組的 res/values/ 目錄。
SELinux 是一個安全機制,可以防止一些惡意的 app 讀取系統檔案,但是這個機制也會導致一些問題,比如錯誤的 Sepolicy rules 可能會導致部分硬體或軟體工作不正常。甚至無法啟動操作系統。
在適配初期我建議將 SELinux 設為寬容
等到硬體和軟體的適配工作基本完成後再將 SELinux 設定為 Enforcing。
關於 Sepolicy rules 的編寫可以參考這些連結:
一般 prebuilt vendor tree 編譯出來的 ROM 大部分硬體都可以正常工作,但是部分機型的硬體可能需要一些額外的修復才能正常工作,比如說指紋,呼吸燈等
⚠️ 注意: 本部分以小米 10S 為例,該機型採用光學螢幕下指紋,Global HBM。如果你的設備是 Local HBM 具體實現方式可能稍有不同
在小米 10S上由於使用的是螢幕下指紋,所以不能直接使用 vendor 內已經編譯好的 Fingerprint 2.1 HAL,在 Android 12 或以上系統需要手動編譯一個 Fingerprint 2.3 HAL 用來處理 UDFPS 事件,在 Android 12 以下系統需要使用 Lineage inscreen fingerprint HAL 來處理指紋事件。
UDFPS 是 Google 在 Android 12 中新增的一種螢幕下指紋的實現方式,具體可以閱讀相關原始碼
具體實現方式可以參考這個提交歷史
⚠️ 注意: 由於小米 10S 使用 Global HBM,因此我們需要進行 kernel dimming 或 framework dimming,否則在使用指紋解鎖時全螢幕亮度將調至最高,因為小米 10S 使用 prebuilt kernel,因此只能使用 framework 進行 dimming 具體實現參考這個提交
具體實現方式可以參考這個提交歷史
此外我們還需要在 overlay 中設定部分參數, 以使得螢幕下指紋識別功能正常工作, 具體參考這個提交
⚠️ 注意: 由於小米 10S 使用 Global HBM,因此我們需要進行 kernel dimming 或 framework dimming,否則在使用指紋解鎖時全螢幕亮度將調至最高,因為小米 10S 使用 prebuilt kernel,因此只能使用 framework 進行 dimming 具體實現參考這個提交
⚠️ 注意: 由於 Android 13 使用 Kotlin 重寫了 UDFPS 部分,因此上面的實現不相容 Android 13,建議使用 kernel dimming 來獲得更好的體驗,具體提交可以參考這些
通常原廠系統都採用 QCOM BT,因此我們需要一些更改來支援 vendor 中的 QCOM BT,具體可以參考這個提交
Google 在 Android 13 中模組化了多個組件,其中就包括藍牙,但是 vendor 中的 QCOM BT 並不相容這一更改,因此我們需要編譯修改過後的 android.hardware.bluetooth.audio
來停用掉 QCOM BT, 並切換到 AOSP BT
具體實現參考這些提交:
部分設備可能廠商魔改了 libvolumelistener,因此我們需要替換掉 libvolumelistener 中的,具體可以參考這個提交
造成這個的原因有很多種,這裡拿幾種出來講
fastboot -w
格式化 data 分區嘗試使用以下提交來修復 BPF 載入問題
如果以上方法都沒有解決問題,可以嘗試獲取日誌來分析問題
如果設備連線到電腦可以被 adb devices
識別到,便可以使用 adb logcat
獲取 logcat 日誌
可以通過檢查 logcat 中帶 error
, crash
, fatal
等關鍵字的日誌來定位問題
如果設備連線到電腦不能被 adb devices
識別到,則需要獲取 pstore 日誌
⚠️ 注意: pstore 需要在 kernel 中開啟,如果沒有開啟則無法獲取 pstore 日誌
adb pull /sys/fs/pstore
獲取 pstore 日誌可以通過檢查 pstore 日誌中帶 error
, crash
, fatal
等關鍵字的日誌來定位問題
設備卡二屏代表系統已經啟動,kernel 部分已經正常工作,但是系統服務沒有正常啟動
我們可以通過 logcat 日誌來分析問題,具體參考上一節的獲取 logcat 日誌
一般出現該錯誤代表有動態庫沒有正確載入或缺失,具體參考日誌中的報錯然後補全缺失的動態庫
一般出現該錯誤代表沒有正確配置 SELinux,具體參考日誌中的報錯然後修復 SELinux
fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
錯誤一般出現該錯誤代表系統服務出現了崩潰,具體參考日誌中的報錯然後修復崩潰