Android 知識體系 一、平臺架構 Google Android 平臺架構 Google Android 架構 Android 是一個針對多種不同設備類型打造的開放源代碼軟體堆棧。Android 的主要目的是為運營商、OEM 和開發者打造一個開放的軟體平臺,使他們能夠將創新理念變為現實,並推出能 ...
一、平臺架構
Google Android 平臺架構
Google Android 架構
Android 是一個針對多種不同設備類型打造的開放源代碼軟體堆棧。Android 的主要目的是為運營商、OEM 和開發者打造一個開放的軟體平臺,使他們能夠將創新理念變為現實,並推出能夠卓有成效地改善用戶移動體驗的真實產品。
Android 平臺的設計可確保不存在一個集中瓶頸,即沒有任何行業參與者可一手限制或控制其他參與者的創新。這樣,我們不但可以打造功能完善的高品質消費類產品,而且可以完全開放源代碼,供第三方自由定製和移植。
System Apps是個人接觸最快的,APP可實際編寫調試;其他都在手機廠商系統OEM定製。
1.1 Linux Kernel
Android 平臺的基礎是 Linux 內核。例如,Android Runtime (ART) 依靠 Linux 內核來執行底層功能,例如線程和低層記憶體管理。
使用 Linux 內核可讓 Android 利用主要安全功能,並且允許設備製造商為著名的內核開發硬體驅動程式。
1.2 硬體抽象層 (HAL)
硬體抽象層 (HAL) 提供標準界面,向更高級別的 Java API 框架顯示設備硬體功能。HAL 包含多個庫模塊,其中每個模塊都為特定類型的硬體組件實現一個界面,例如相機或藍牙模塊。當框架 API 要求訪問設備硬體時,Android 系統將為該硬體組件載入庫模塊。
1.3 Android Runtime
對於運行 Android 5.0(API 級別 21)或更高版本的設備,每個應用都在其自己的進程中運行,並且有其自己的 Android Runtime (ART) 實例。ART 編寫為通過執行 DEX 文件在低記憶體設備上運行多個虛擬機,DEX 文件是一種專為 Android 設計的位元組碼格式,經過優化,使用的記憶體很少。編譯工具鏈(例如 Jack)將 Java 源代碼編譯為 DEX 位元組碼,使其可在 Android 平臺上運行。
ART 的部分主要功能包括:
- 預先 (AOT) 和即時 (JIT) 編譯
- 優化的垃圾回收 (GC)
- 在 Android 9(API 級別 28)及更高版本的系統中,支持將應用軟體包中的 Dalvik Executable 格式 (DEX) 文件轉換為更緊湊的機器代碼。
- 更好的調試支持,包括專用採樣分析器、詳細的診斷異常和崩潰報告,並且能夠設置觀察點以監控特定欄位
在 Android 版本 5.0(API 級別 21)之前,Dalvik 是 Android Runtime。如果您的應用在 ART 上運行效果很好,那麼它應該也可在 Dalvik >上運行,但反過來不一定。
Android 還包含一套核心運行時庫,可提供 Java API 框架所使用的 Java 編程語言中的大部分功能,包括一些 Java 8 語言功能。
1.4 Native C/C++ Library
許多核心 Android 系統組件和服務(例如 ART 和 HAL)構建自原生代碼,需要以 C 和 C++ 編寫的原生庫。Android 平臺提供 Java 框架 API 以嚮應用顯示其中部分原生庫的功能。例如,您可以通過 Android 框架的 Java OpenGL API 訪問 OpenGL ES,以支持在應用中繪製和操作 2D 和 3D 圖形。
如果開發的是需要 C 或 C++ 代碼的應用,可以使用 Android NDK 直接從原生代碼訪問某些原生平臺庫。
1.5 Java API Framework
您可通過以 Java 語言編寫的 API 使用 Android OS 的整個功能集。這些 API 形成創建 Android 應用所需的構建塊,它們可簡化核心模塊化系統組件和服務的重覆使用,包括以下組件和服務:
- 豐富、可擴展的視圖系統,可用以構建應用的 UI,包括列表、網格、文本框、按鈕甚至可嵌入的網路瀏覽器
- 資源管理器,用於訪問非代碼資源,例如本地化的字元串、圖形和佈局文件
- 通知管理器,可讓所有應用在狀態欄中顯示自定義提醒
- Activity 管理器,用於管理應用的生命周期,提供常見的導航返回棧
- 內容提供程式,可讓應用訪問其他應用(例如“聯繫人”應用)中的數據或者共用其自己的數據
開發者可以完全訪問 Android 系統應用使用的框架 API。
1.6 System Apps
Android 隨附一套用於電子郵件、簡訊、日曆、互聯網瀏覽和聯繫人等的核心應用。平臺隨附的應用與用戶可以選擇安裝的應用一樣,沒有特殊狀態。因此第三方應用可成為用戶的預設網路瀏覽器、簡訊 Messenger 甚至預設鍵盤(有一些例外,例如系統的“設置”應用)。
系統應用可用作用戶的應用,以及提供開發者可從其自己的應用訪問的主要功能。例如,如果您的應用要發簡訊,您無需自己構建該功能,可以改為調用已安裝的簡訊應用向您指定的接收者發送消息。
二、AOSP : Android源碼下載
編號 | 概念 | 備註 |
---|---|---|
1 | 代號、標記和 Build 號 | Android 版本(列表) |
2 | Android 開發者 Codelab | |
3 | Android 平臺術語表 | |
4 | 搭建構建環境 | |
5 | 源代碼控制工具 | git、repo |
6 | 下載源代碼 | AOSP : Android源碼下載 |
7 | Soong 構建系統 | |
8 | 搭建編譯環境、 編譯 Android | |
9 | 使用AS查看Android源碼 | sourceinsight 改用 AndroidStudio 查看 Android 源碼 |
10 | 同步國內AOSP代碼相關錯誤 |
屬性值
prop屬性 | android.os.SystemProperties 屬性 |
settings屬性 | settings屬性 |
Feature屬性 | pm list features |
adb 命令
命令 | 功能 | 相關文章 |
---|---|---|
adb shell screencap -p /sdcard/01.png | 截屏 | 使用adb命令對手機屏幕截圖 |
adb shell screenrecord /sdcard/demo.mp4 | 錄製手機屏幕,預設錄製時間為180s | Android4.4屏幕錄製命令screenrecord |
adb bugreport > bugreport.txt | bugreport 日誌 | |
adb shell dmesg > dmesg.txt | dmesg 日誌 | |
adb logcat -d -v time -b "main" > main.txt | main 日誌 | |
adb logcat -d -v time -b "system" > system.txt | system日誌 | |
adb logcat -d -v time -b "events" > events.txt | events 日誌 | |
adb shell dumpsys sensorservice | 查看Sensorservice信息 | sensorservice相關dump |
Events
Event日誌關鍵字:EventLogTags.logtags
三、Android 通信機制
Android系統基於Linux kernel,IPC(Inter-Process Communication, 進程間通信)方式在Linux中有
管道pipe、消息隊列message queue、共用記憶體share memory、套接字socket、信號signal
等IPC機制。
Android中還有Binder
IPC機制,Android系統中的Zygote進程的IPC採用的是Socket機制,在Framework與App之間更多的是採用Binder IPC方式完成跨進程間的通信。
對於Android上層架構中,在同一個進程的線程之間相互通信往往採用的Handler消息機制
。
3.1 Binder
Linux Kernel是開源系統,所開放源代碼許可協議GPL保護,
Binder Driver
運行在Linux Kernel是GPL協議。用戶空間採用Apache-2.0協議,內核空間與用戶空間(即在GPL協議與Apache-2.0協議)之間的Lib庫中採用BSD證授權方法,GPL協議限定在Linux Kernel,有效隔斷了GPL的傳染性,仍有較大爭議。開源與商業化共存的一個成功典範。Binder 是基於開源的OpenBinder實現的,而OpenBinder的作者在Google工作,直接採用 Binder 作為核心的IPC機制。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/affc241df7f74f639a0ff580f747af2e.png =600x)
序號 | 文章名 | 概述 |
---|---|---|
0 | 為什麼 Android 要採用 Binder 作為 IPC 機制? | 【Android,在爭議中逃離 Linux 內核的 GPL 約束】 |
0 | 使用 Binder IPC | 多個 Binder 域:/dev/binder 、/dev/hwbinder 、/dev/vndbinder |
1 | Binder系列1-Binder Driver | /dev/binder 運行在Linux kernel |
2 | Binder系列2-ServiceManager | SM啟動,添加/獲取Service |
3 | Binder系列3-framework層 | Zygote啟動時AndroidRuntime::startReg中register_jni_procs() ,JNI調用到Native |
4 | Binder 域 | 關註/dev/vndbinder與/dev/binder共用一套libbinder,defaultServiceManager()獲取前需要切換 |
3.2 Socket
Android中IPC進程間通信使用最多的是Binder,其次是socket。
這裡socket是Unix domain Socket。不同於Network Socket基於TCP/IP協議棧
Socket通信方式也是C/S架構
實例 | 描述 |
---|---|
Zygote用於fork進程 | system_server創建進程是通過socket向zygote進程發起請求 |
3.3 Handler消息機制
Handler消息機制用於同進程的線程間通信,Handler消息機制是由一組MessageQueue、Message、Looper、Handler共同組成的。
3.4 Android 介面定義語言 AIDL\HIDL
Android 介面定義語言 (AIDL) Android 介面定義語言 (AIDL) 是一款可供用戶用來抽象化 IPC 的工具。以在 .aidl 文件中指定的介面為例,各種構建系統都會使用 aidl 二進位文件構造 C++ 或 Java 綁定,以便跨進程使用該介面。
Android 介面定義語言 (HIDL) Android 8.0 重新設計了 Android 操作系統框架(在一個名為“Treble”的項目中),以便讓製造商能夠以更低的成本更輕鬆、更快速地將設備更新到新版 Android 系統。在這種新架構中,HAL 介面定義語言(HIDL,發音為“hide-l”)指定了 HAL 和其用戶之間的介面,讓用戶無需重新構建 HAL,就能替換 Android 框架。在 Android 10 中,HIDL 功能已整合到 AIDL 中。此後,HIDL 就被廢棄了,並且僅供尚未轉換為 AIDL 的子系統使用。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/274ae919419b45068cafa2f5045b1573.png =550x)
適用於 HAL 的 AIDL
四、Android核心
4.1 系統啟動
Android 設備啟動必須經歷3個階段,即 Boot Loader、Linux Kernel 和 Android系統服務。嚴格來說,Android系統實際上是運行於Linux內核上的一系列 “服務進程”,並不算一個完整意義上的“操作系統”。這些進程維持設備正常運行,而他們的 “老祖宗” 就是 init。通過解析 init.rc 腳本來構建出系統的初始形態。
Android系統啟動過程從下往上,由
Boot Loader
引導開機,然後依次進入 ->Linux Kernel
->Native
->Framework
->App
階段 | 啟動 | 描述 |
---|---|---|
Loader | Boot Rom | 當電源按下,引導晶元代碼開始從預定義的地方(固化在ROM)開始執行。載入引導程式到RAM,然後執行。 |
Boot Loader | 引導程式是在Android操作系統開始運行前的一個小程式。它不是Android操作系統的一部分。引導程式是OEM廠商或者運營商加鎖和限制的地方。引導程式分兩個階段執行。第一個階段,檢測外部的RAM以及載入對第二階段有用的程式;第二階段,引導程式設置網路、記憶體等等。 | |
Linux Kernel | swapper | 0號進程是linux啟動的第一個進程,它的task_struct的comm欄位為"swapper",所以也成為swpper進程。當系統中所有的進程起來後,0號進程也就蛻化為idle進程,當一個core上沒有任務可運行時就會去運行idle進程。一旦運行idle進程則此core就可以進入低功耗模式了,在ARM上就是WFI。pid=1,init進程;pid=2,kthreadd進程 |
Native C/C++Library | init | 解析 init.rc 文件 |
Zygote | Zygote進程是由init進程通過解析 init.rc 文件後 fork 生成 | |
Java API Framework | SystemServer | System Server進程,是由Zygote進程fork而來,System Server是Zygote孵化的第一個進程 |
4.1.1 系統啟動流程
https://elinux.org/Android_Booting
https://elinux.org/Android_Zygote_Startup
http://www.androidenea.com/2009/07/system-server-in-android.html
https://elinux.org/Android_Logging_System
序號 | 概述 | 簡要 |
---|---|---|
0 | Android系統啟動 | Android機器啟動關鍵進程啟動流程,Launcher在R上又差異 |
1 | Android Init Language : init.rc | init.rc語法,查看system\core\init\README.md文件說明 |
2 | init進程 | 粗略梳理init進程啟動後相關初始工作 |
3 | init進程——從kernel Log查看 | 從kernel Log對照查看 |
4 | ap日誌查看Android啟動流程 | Events日誌查看啟動 |
5 | Zygote進程 | |
6 | SystemServer進程 | Zygote fork出進程system_server |
7 | Launcher啟動過程 | system_server fork出進程launcher |
8 | ActivityThread應用進程 | fork;ActivityThread |
4.1.2 守護進程
序號 | 守護進程daemons | 簡要 |
---|---|---|
1 | debuggerd | |
2 | installd | installd守護進程 |
3 | lmkd | system/memory/lmkd/lmkd.rc system/memory/lmkd/lmkd.cpp |
4 | logd | |
5 | adbd |
4.1.3 Syscall && JNI
- Native與Kernel之間紐帶SysCall
- Java層與Native(C/C++)層之間紐帶JNI:Android JNI原理
4.2 系統服務
Android 中有大量的服務,都是基於Binder來交互的(Android 中的絕大部分 Service 都會繼承BinderService類,BinderService 是 Android Service 框架的主要類,是個模板類,它提供了 Service 的生命周期管理、進程間通信、請求響應處理等功能)。
系統孵化System Server進程後,由System Server負責啟動和管理整個Java framework中服務,在 SystemServer.java 的 startBootstrapServices、startCoreServices、startOtherServices 方法中啟動
簡稱 | 服務 | 描述 |
---|---|---|
AMS | ActivityManagerService | 四大組件管理控制 |
WMS | WindowManagerService | Window視窗圖形管理 |
PKMS | PackageManagerService | apk安裝卸載 |
PMS | PowerManagerService | 電源管理服務 |
IMS | InputManagerService | 主要負責觸摸事件的採集 |
IMMS/IME | InputMethodManagerService | 用於控制顯示或隱藏輸入法面板的類 |
SensorService | SensorService | 感測器上報,軟體或硬體實現 |
JobSchedulerService | JobSchedulerService | 滿足網路、電量、時間等一定預定條件而觸發的任務 |
NMS | NotificationManagerService | 通知處理 |
ActivityManagerService
序號 | 文章名 | 概述 |
---|---|---|
1 | ActivityManagerService啟動-android12 | AMS啟動,初始化,systemReady |
2 | AMS:startActivity桌面啟動應用 | 四大組件中Activity冷啟動;更多關註4.3 四大組件 |
WindowManagerService
PackageManagerService
序號 | 文章名 | 概述 |
---|---|---|
1 | PackageManagerService啟動 | PackageManagerService(簡稱PKMS) 管理著所有跟package相關的工作,常見的比如安裝、卸載應用。 |
PowerManagerService
InputManagerService
序號 | Android11 | Android12 | 概述 |
---|---|---|---|
1 | ANR InputDispatching TimeOut超時判斷 | InputDispatching TimeOut | |
2 | IMS:InputManagerService啟動簡要 | InputManagerService啟動-Android12 | IMS啟動概要,溫故知新 |
3 | IMS:InputReader線程獲取輸入事件 | InputReader線程獲取輸入事件-Android12 | EventHub獲取處理,轉遞給InputDispatcher |
4 | IMS:InputDispatcher線程分發事件 | InputDispatcher線程分發事件-Android12 | 主要走一遍InputDispatcher線程正常分發流程,關註mInboundQueue、outboundQueue |
InputChannel通道建立-Android12 | InputChannel \ InputEventReceiver | ||
5 | IMS:InputChannel通過socket發送Input給App | InputChannel發送Input給App-Android12 | InputChannel通過socket發送,InputStage 責任鏈處理 |
6 | IMS:InputDispatcher 接收反饋進行下一次發送 | InputStage 責任鏈分發最後都會有個完成 finishInputEvent 反饋 | |
7 | IMS:injectInputEvent註入Input事件 | 註入 Input 事件直接加入到mInboundQueue由InputDispatcher分發,沒有經過InputReader | |
8 | 導航鍵或手勢導航註入事件 | 查看injectInputEvent調用 | |
9 | IMS:開發者選項Touch點顯示 | 顯示 TouchInputMapper 事件 | |
10 | IMS:開發者選項中指針位置 | 繪製 TouchInputMapper 事件十字畫線 | |
11 | IMS:鍵盤滑鼠接入判斷 | EventHub添加外界設備,查看sources信息 | |
12 | IMS:鍵盤滑鼠事件 | 滑鼠CursorInputMapper事件處理 | |
13 | IMS:EventHub 設備添加和InputDevice轉化 | IMS的設備Device獲取並轉化為InputDevice | |
14 | IMS:EventHub設備底層上報Input事件對象處理 | 底層上報input_event 到通知InputDispatcher |
|
15 | IMS:Input事件可攔截位置 | Input事件特殊攔截功能的地方 | |
16 | IMS:AccessibilityService輔助服務攔截註入Input事件 | AccessibilityInputFilter攔截Input事件 | |
17 | IMS:InputDispatcher的焦點設置 | 瞭解Input中FocusedWindow從WMS設置 | |
18 | 案例:Input事件有焦點App無焦點視窗 | BUG案例 | |
19 | Android 12關於Input觸摸事件的行為變更 | 不受信任的觸摸事件被屏蔽 | |
20 | Android12特性“不受信任的觸摸事件被屏蔽”其他細節 | 熟悉相關屬性,瞭解不攔截情況 | |
21 | Drag and drop拖放框架 | APP和ViewRootImpl、View之間拖放 | |
22 | IMS:InputManagerService小結 | IMS小結 | |
23 | IMS:MotionEvent 坐標點(上) | ||
24 | 案例:Android12上“顯示刷新頻率“點擊無效 | BUG案例 |
InputMethodManagerService
SensorService
序號 | Android11 | Android12 | 概述 |
---|---|---|---|
1 | Android Sensor 概覽 | SensorService大致流程梳理 | |
2 | SensorService啟動 | SensorService啟動-Android12 | SensorService啟動知識點 |
3 | SensorService數據傳遞給APK | SensorService數據傳遞給APP-Android12 | Sensor數據傳遞流程 |
4 | 計步感測器TYPE_STEP_COUNTER | 計步感測器相關瞭解 | |
5 | Android獲取這顆Sensor對象 | APP獲取Sensor對象-Android12 | 獲取sensor硬體sensor_t流程 |
6 | Android應用監聽Sensor獲取的SensorEvent對象 | APP註冊SensorEventListener-Android12 | Android應用監聽Sensor獲取的SensorEvent對象sensors_event_t |
7 | Sensor相關Google認證 | 記錄Sensor相關CTS問題 | |
8 | sensorservice相關dump | dump查看sensorservice信息 | |
9 | SensorService開機啟動耗時探討 | connectHidlService() | |
10 | SensorService小結 | 小結一下 |
NotificationManagerService
序號 | 文章名 | 概述 |
---|---|---|
1 | Notifications 通知 | NotificationManagerService通知流程梳理 |
2 | NotificationManagerService啟動(“Notifications 通知”拆解) | NMS服務啟動 |
3 | APP請求系統通知(“Notifications 通知”拆解) | Notification通知流程及其部分Event日誌 |
4 | Notifications通知到SystemUI(“Notifications 通知”拆解) | Notification與SystemUI之間橋梁 |
CameraService
序號 | 文章名 | 概述 |
---|---|---|
0 | Camera概覽 | 相機架構 |
1 | CameraService啟動-Android12 | |
2 | CameraProvider進程-Android12 | |
3 | CameraServiceProxy啟動-Android12 | |
4 | APP使用相機CameraX | CameraX簡要使用,關註預覽用例preview、捕獲用例imageCapture和分析用例imageAnalyzer |
4.3 四大組件
Android應用的四大組件Activity,Service,BroadcastReceiver, ContentProvider
四大組件 | 文章 | 概要 |
---|---|---|
Activity | ||
應用內部啟動startActivity-Android12 | 相關查看 AMS:startActivity桌面啟動應用 ActivityManagerService啟動-android12 ActivityThread應用進程 |
|
Activity相關初始化-Android12 | ActivityThread、Instrumentation、Application、Activity | |
四大組件:Activity生命周期-Android12 | Android P Basic lifecycle transaction containers |
|
Service | ||
startService啟動過程-Android12 | ||
bindService啟動過程-Android12 | ||
unbindService流程-Android12 | unbindService() 關閉連接,當所有綁定全部取消後,系統即會銷毀該服務。 | |
ANR service TimeOut 超時判斷 | ||
BroadcastReceiver | ||
BroadcastReceiver機制-Android12 | ||
ANR Broadcast TimeOut 超時判斷 | ||
ContentProvider | ||
ContentProvider簡要說明 | 瞭解應用場景和簡單使用 |
4.4 圖形界面SurfaceFlinger、WMS
Android 屏幕刷新機制
Android Choreographer 源碼分析
android屏幕刷新顯示機制
通俗易懂的Android屏幕刷新機制
“終於懂了” 系列:Android屏幕刷新機制—VSync、Choreographer 全面理解!
Android圖形系統綜述(乾貨篇)
序號 | 文章名 | 說明 |
---|---|---|
1 | Android 圖形組件簡介 | 看看有什麼東西就行 |
2 | Android 顯示刷新頻率 | 開發者選項->顯示刷新頻率 |
4.5 穩定性
Stability問題現象: 死機重啟、自動關機、無法開機、凍屏、黑屏以及閃退、無響應等情況; 基本都是整機問題,用戶不能使用,穩定性指標至關重要。從技術層面來劃分無外乎兩大類: 長時間無法執行完成(Timeout) 以及異常崩潰(crash).
4.6 性能
測試記憶體、cpu、fps、頁面載入時間等性能指標
系統跟蹤概覽
“系統跟蹤”就是記錄短時間內的設備活動。系統跟蹤會生成跟蹤文件,該文件可用於生成系統報告。此報告可幫助您瞭解如何最有效地提升應用或游戲的性能。
Systrace系列
Android Systrace 基礎知識
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210714004543379.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIzNDUyMzg1,size_16,color_FFFFFF,t_70 =350x)
性能工具Systrace
序號 | 文章 | 簡要 |
---|---|---|
0 | 系統跟蹤概覽 | android developers |
0 | 通過命令行上捕獲系統跟蹤記錄 | android developers |
0 | 瀏覽 Systrace 報告 | android developers |
0 | Android Systrace 基礎知識 | 原文作者:Gracker 或者高爺 |
五、APP
5.1 Kotlin
developers KOTLIN
https://kotlinlang.org/
https://play.kotlinlang.org/
Kotlin 教程
https://www.npmjs.com/package/kotlin
在 Android 開發中優先採用 Kotlin
5.1.1 Kotlin 基本語法
序號 | 概述 |
---|---|
1 | Kotlin 基本類型 |
2 | 學習 Kotlin 編程語言 |
3 | 使用 Kotlin 編寫您的第一個程式 |
4 | repeat 語句 |
* | Android 上的 Kotlin 協程 |
* | Android 上的 Kotlin 數據流 |
5.1.2 Android Kotlin 使用入門
序號 | Android Kotlin 使用入門 |
---|---|
1 | 創建您的首個 Android 應用 |
5.1.3 Kotlin 常見問題
序號 | 概述 |
---|---|
1 | Kotlin 有而 Java 沒有的東西 |
5.2 Android Launcher
packages/apps/Launcher3
5.3 Android SystemUI
frameworks\base\packages\SystemUI
序號 | 概述 |
---|---|
1 | SystemUI啟動,及其SystemUIService啟動 |
2 | Notifications通知到SystemUI(“Notifications 通知”拆解) |
5.4 Android Settings
5.5 Apk反編譯
apktool 、dex2jar、jd-gui
JADX
Jeb
序號 | 概述 |
---|---|
1 | Apk反編譯 -- 記錄 |
5.6 Android Games
Unity 引擎
cocos2d-x 引擎
LGame 游戲引擎 : LGame_百度百科
序號 | 概述 |
---|---|
1 | g2048游戲1-android \ g2048游戲2-android \ g2048游戲3-android |
2 | Android使用cocos2d-x引擎 |