# 簡析 Android Device Tree - 繁體中文 ``` 注意:本文介紹的 Devie Tree 不是 Kernel 中的 Device Tree,而是存放在 ROM 原始碼中 device 資料夾內的裝置特有原始碼。 ``` ## 前言 Devie Tree 儲存了編譯 ROM 所需的設定值,以及部分對於裝置功能的延伸(例如 IFAA 和 XiaomiParts)。本文將對 [TH779 Studio - ROM (GitHub Organization) 下的 Redmi K20 Pro Device Tree](https://github.com/hh2333-studio-rom-opensource/android_device_xiaomi_raphael) 做簡易的架構分析,盡量用普通人能理解的思維說明每一部分的不同作用,目的是讓大多數人知道 Device Tree 的組成以及给想學寫 Device Tree 的人做一個參考。 ## 開始 首先我們看 Device Tree 的結構,應該是這樣的: ``` . ├── Android.bp ├── Android.mk ├── AndroidProducts.mk ├── audio ├── bluetooth ├── BoardConfig.mk ├── compatibility_matrix.xml ├── config.fs ├── configs ├── device.mk ├── extract-files.sh ├── fingerprint ├── fod ├── gps ├── init ├── libhidl ├── light ├── lineage.dependencies ├── lineage_raphael.mk ├── manifest.xml ├── media ├── odm.prop ├── org.ifaa.android.manager ├── overlay ├── overlay-lineage ├── parts ├── proprietary-files.txt ├── README.md ├── recovery ├── releasetools.py ├── rootdir ├── rro_overlays ├── seccomp ├── setup-makefiles.sh ├── system_ext.prop ├── system.prop ├── vendor.prop └── wifi ``` 我們從圖中可以看到,此 Device Tree 是由一堆 makefile、blueprint 以及許許多多的配置文件和 HAL 組成。 ## Makefile 首先我們來介紹幾個重要的 makefile。 * Android.mk Android.mk 往往用於向編譯系統描述源文件、應用程式以及一些共用庫。Device Tree 的根目錄中往往會有一個 Android.mk,這個 Android.mk 與前面說的作用有部分不同,它往往在編譯檢查時判斷要編譯的裝置是否使用此 Device Tree,並對不使用此 Device Tree 的裝置隱藏掉此 Device Tree 下的 Android.mk(當然,此 Devie Tree 中在 Android.mk 定義的一些同名 modules 仍然可以造成衝突,稍後我们將導入 Soong 命名空間這個概念)。 * AndroidProducts.mk 這個是用來指定設備特有 makefile 的。我們可以看到,`PRODUCT_MAKEFILES` 這個 flag 指定了 lineage_raphael.mk 作為設備的構建 makefile,不過需要說的是,像 Google 開源的 Pixel Device Tree 往往會同時定義多個設備特有 makefile,每個 makefile 分別對應不同的 target。例如我們輸入的是 `lunch lineage_raphael-userdebug`,構建系統就會在 `PRODUCT_MAKEFILES` 中尋找到 `PRODUCT_NAME` 為 lineage_raphael 的 target 並使用包含其的 makefile 作為特有 makefile 來進行編譯。此外,細心的讀者還會發現本文所解析的設備樹中還有 `COMMON_LUNCH_CHOICES` 這樣一個 flag,這是用於指定設備支持的 Build Type(eng、user 和 userdebug),不同 Build Type 的區別都可以在網路上找到,本文不再做說明。 * BoardConfig.mk 和它的名字一樣,這個 makefile 是用來存放手機相關配置訊息的,例如分區、HAL 的編譯選項、架構資訊等,都是在這個 makefile 中定義的,這個裡面的相關 flag 都可以在 ROM 原始碼中找到(當然有些 flag 是在 Device Tree 裡定義的,也可以找到)。 * device.mk 這個 makefile 的名字可以為任意,甚至可以省略。因為它是被 `PRODUCT_MAKEFILES` 中指定的 makefile 包含的,所以這裡面的內容也可以直接定義在指定的 makefile 中。這個的主要作用是指定設備應當編譯的模組(使用 `PRODUCT_PACKAGES` 這個 flag)和文件(使用 `PRODUCT_COPY_FILES` 這個 flag),複製的檔案大多數都是 Device Tree 中的配置文件,當然有些未被修改的配置文件(例如權限相關還有部分 audio 和 media 配置)也可以用這個 flag 來複製到設備的相應位置中。 * lineage_raphael.mk 這個我之前已經說過,這是指定在 `PRODUCT_MAKEFILES` 中的 makefile,當 lunch 的時候,構建系統會在這些 makefile 中尋找到相應的 target 並載入相關變數以便構建。因為 build/make 中的部分內容是通用的,所以這個 makefile 往往會從 build/make 中繼承一些 makefile,繼承後編譯系統就會一起載入這些 makefile 的相關內容。 ## 配置文件 * audio、gps、media、wifi 等 正如其字面意思一樣,這些文件夾內存放的都是與之相關的配置文件,當部分配置文件不方便歸類的時候可以放到 configs 文件夾下。當然,放完配置文件後需要在 device.mk 中使用 `PRODUCT_COPY_FILES` 定義文件。 * seccomp Android O 使用 Linux 內核中的安全計算模式,使得未使用的系統調用無法被應用程式訪問。這個文件夾 * overlay * rootdir * manifest.xml 和 compatibility_matrix.xml * system.prop 和 vendor.prop ###### tags: `Android`