---
title: 'Android Emulator、QEMU'
disqus: kyleAlien
---
Android Emulator、QEMU
===
## OverView of Content
詳細的可以看看官方的 **[Emulator](https://developer.android.com/studio/run/emulator-commandline)** 介紹文檔,在使用模擬器指令之前也先看看 [**Avd**](https://hackmd.io/02U2lU50RDWQsvh6Ui37kQ?view#AVD-Manager) 的創建
> QEMU 是由法國大神 Fabrice Bellard 撰寫出來,他另一個有名的開源項目就是 [**Ffmpeg**](https://github.com/FFmpeg/FFmpeg) (影音常用 Library)
[TOC]
## Emulator 概述
模擬器可以客製化各種硬體設備,這方便我們測試程式在多種情況下的運行狀況,這可以為我們減少許多時間、金錢~
### 虛擬化架構 - OS/VMM
* 首先我們介紹虛擬化技術
**虛擬化技術**(`virtualization`):簡單來說就是通過特別手段,**模擬一個不存在的物件**(軟體:系統、伺服器...;硬體:硬碟、CPU...)
:::info
* **雲計算**:
**虛擬化技術是實現 雲計算 的重要基礎**
:::
虛擬化技術慢慢轉變為 **控制程序**,再後來慢慢轉變為 **管理程序** (`Hypervisor`) 或是 虛擬機監控(`Virtual Machine Monitor`, VMM)
* **有關於 OS、VMM**:
軟體 GuestOS(虛擬機)則運行在 VMM 之上;而又可細分為兩種類型
1. **裸機型**(`Bare-Metal Hypervisor`, 也稱為 `Type 1 Hypervisor`):虛擬機運行在 VMM 之上,而 VMM 直接運行在硬件之上
> 這種虛擬機它可以直接面對硬體,**不需要底層操作系統的支撐**;VMM 本身就是 GuestOS 直接的宿主
:::info
* 像是 `Oracle VM Server for SPARC`、`KVM`、`VMWare EXS/ESXi`、`Microsoft Hyper-V`... 等等
:::
2. **宿主型**(`Hosted Hypervisor`, 也稱為 `Type 2 Hypervisor`):虛擬機運行在仍 VMM,不過 VMM 運行在虛擬機的作業系統(`Host OS`)
> VMM 之下仍有一個操作系統,就像是一個普通的軟體
:::info
* 像是 `VirtualBox`、`VMWare Workstation`、`Bhyve`... 等等
:::
> 
:::success
* **OS 之間的差異**(例如:Windows、Linux 等)
* 主機作業系統(Host OS):這是運行在物理硬體上的實際作業系統,**它管理硬體資源**,提供虛擬化軟體運行所需的環境,並承擔虛擬化軟體和虛擬機之間的中介角色
* 虛擬機軟體中的作業系統(Guest OS):每個虛擬機都運行自己的獨立的作業系統。這些作業系統在虛擬機中運行,並且它們可能是不同的作業系統。這些作業系統在虛擬化軟體提供的虛擬環境中運行,並與虛擬硬體交互,以實現虛擬化
:::
### 虛擬化 OS - 分類
* 基於上述虛擬化的架構,我們可以分類一下虛擬機的特點都不同(針對 `VMM` 與 `Guest OS` 之間的關係):
> 全虛擬化技術不分裸機型、宿主型
1. **全虛擬化(`Full virtualization`)**
| 特點 | 補充 |
| - | - |
| 完整的硬體模擬 | CPU, PhyMem, Disk, Clock... 等等 |
| 實現難點 | 如何 **Mapping 不同硬體的不同指令、協定**;並要 **相互隔離** |
| 軟體 | `KVM`, `Oracle VM`, `Virtual PC`, **`QEMU`**... 等等 |
2. **部分虛擬化(`Partial virtualization`)**
與 全虛擬化 類似,不過運行在部分虛擬化平台之上的 `Guest OS` 可以針對虛擬化平台開出的介面做一些特殊實現
> 介面實現是一種好處,但同時也是比較煩的部分
| 特點 | 補充 |
| - | - |
| 介面實現 | 這樣速度較快、架構也較為精簡(但較麻煩) |
| 軟體 | `Xen`, `Micrisift Hyper-V`... 等等 |
3. **硬件輔助虛擬化(`Hardware-assisted virtualization`)**\
這個技術其實是協助(完整化)上述的兩種虛擬化方式,**它借助專門針對虛擬化技術而提供的硬體支持來改善虛擬化的不足**
> 可以讓 `VMM` 運行起來更像是真實物理機器
| 特點 | 補充 |
| - | - |
| 軟體 | `KVM`, `Xen`, `VMware workstation`, `Virtual Box`... 等等 |
## QEMU 概述
> 學習 QEMU 的最佳方式當然是查看 [**官方文檔**](https://www.qemu.org/documentation/),以下只做個簡單的總結
* **QEMU 有兩種模式**
1. **全系統模式**:QEMU 可以模擬出一套完整的系統,包括 CPU、外圍設備
2. **用戶模式**:QEMU可以在一個 CPU 之上運行針對另一個 CPU 所編譯的程式(可運行另一個 CPU 的指令集!)
### QEMU 安裝
* 安裝 QEMU 可以透過一些 PackageManager,也可以透過下載原始碼來編譯
* 透過 **PackageManager**
```shell=
# ubunti
sudo apt install -y qemu
# read hat
yum install qemu
# MacOS
brew install -y qemu
```
* **下載原始碼來編譯**
```shell=
# autoconf 配置
./configure
make
make install
```
### QEMU 控制指令
* 首先 QEMU 命令有許多種,你必須針對不同平台運行運行不同指令;假設你要啟動的模擬器 CPU 指令為 `x86_64`,那你就要使用 `qemu-system-x86_64` 指令;
:::info
* 我們可以在不同 CPU 架構上運行另一個 CPU 模擬器
:::
> 
* **QEMU 基礎設置參數**(以 `qemu-system-x86_64` 指令為例)
* **通用指令**
| Options | 功能 |
| - | - |
| `-h` | 取得幫助資訊 |
| `-version` | 該指令的版本 |
* **系統相關選項**
| Options | 功能 | 補充 |
| - | - | - |
| `-machine` <模擬機器> | 選項是用來選擇虛擬機器的模擬型號和硬體特性 | 可使用 `-machine help` 查詢 |
| `-cpu` <CPU 類型> | 選項是用來選擇虛擬機器所使用的虛擬 CPU 型號,它會影響虛擬機器的性能和特性 | 可使用 `-cpu help` 查詢 |
| `-smp` <數量> | 模擬 CPU 核心數量;不同硬件有不同限制 | 預設為 1 |
| `-m` <大小> | 虛擬記憶體槽、大小 | 默認 128M |
| `-fda` <檔案> | 將 ”檔案“,作為模擬器的儲存設備 | 還包括 `-fdb`、`-hda`、`-hdb`、`-hdc`、`-hdd`、`-cdrom` |
| `-drive` [Options] | 創建一個新設備 | - |
| `-sd` <檔案> | 指定 SD 卡 | - |
| `-mtd` <檔案> | 指定 Flash 設備 | - |
| `-m` <語言> | 鍵盤語言 | 預設為 `en-us` |
| `-audiodev` [Options] | 音頻子系統設定 | 可使用 `-audio-help` 查詢 |
| `-boot` [Options] | 啟動順序 | - |
| `-cdrom` <檔案> | 指定 Cdrom 的 image | - |
* `x86_64` 可選的 模擬機器
> 
* `x86_64` 可選的 CPU 類型
> 
:::info
* 針對 `Linux/Multiboot` 系統選項
| Options | 功能 | 補充 |
| - | - | - |
| `-kernel` <bzImage\> | 將 bzImage 指定文件作為內核映像檔 | - |
| `-initrd` <檔案> | 指定一個檔案作為系統的初始 ramdisk,用於啟動過程中 | ramdisk 是 Bootloader 讀取的硬體空間 |
| `-dtb` <檔案> | 指定一個檔案作為裝置樹映像,描述虛擬硬體的信息 | 裝置樹是一種描述硬體設備和配置的數據結構,用於幫助作業系統識別和操作硬體 |
:::
* **USB 相關選項**
| Options | 功能 | 補充 |
| - | - | - |
| `-usb` | 啟動 USB 控制器 | 預設關閉 |
| `-usbdevice` <名稱> | 添加 USB 設備(滑鼠、移動硬碟、串口設備... 等等) | - |
| `-device driver` [Options] | 添加設備驅動 | 可使用 `-device help`、`-device driver,help` 查詢|
* **文件系統 相關選項**
| Options | 功能 | 補充 |
| - | - | - |
| `-fsdev local,id=<id>,path=<path>` [Options] | 定義新的文件系統設備 | - |
| `-virtfs local` [Options] | 定義虛擬文件系統 | |
| `-name` <名稱> | 設定 Guest 名 | - |
| `-uuid` <UUID\> | 設定系統 UUID | - |
* **顯示 相關選項**
| Options | 功能 | 補充 |
| - | - | - |
| `-display` <類型> | 顯示類型 | `dbus`, `cocoa`, `none`... 等等 |
| `-nographic` | 不使用螢幕輸出,改為 CLI 通訊 | - |
| `-full-screen` | 全屏 | - |
| `-rotat` | 螢幕左旋 | 並非每種螢幕都可旋轉 |
* **網路 相關選項**
| Options | 功能 | 補充 |
| - | - | - |
| `-netdev user` [Options] | 創建使用者模式網路接口 | 在虛擬機器和主機之間建立 NAT 或端口轉發的簡單方法 |
| `-netdev tap` [Options] | 創建 TAP 網路接口 | 可以與主機中的實際網路接口相連,使虛擬機器在網路上表現得像一個獨立的主機 |
| `-netdev bridge` [Options] | 創建橋接網路接口 | 將虛擬機器的網路接口連接到主機上的橋接網路,使虛擬機器與實際網路相連 |
| `-netdev socket` [Options] | 創建 Socket 連接網路接口 | 通過 Socket 連接將虛擬機器連接到主機或其他虛擬機器 |
| `-netdev vde` [Options] | 創建 VDE 網路接口 | 與 VDE(`Virtual Distributed Ethernet`)集成,允許虛擬機器進行虛擬網路連接 |
| `-netdev vhost-user` [Options] | 創建 vhost-user 網路接口 | 通過共享記憶體文件在虛擬機器和主機之間實現高效的網路通信 |
* **調適 相關選項**
| Options | 功能 | 補充 |
| - | - | - |
| `-serial` <dev\> | 為模擬器指定串口設備 | Window 串口訊息 COMx,Linux 串口訊息 ttySx |
| `-monitor` <dev\> | 將虛擬機的 monitor 轉向主機的 dev 上 | - |
| `-pidfile` <檔案> | 將 QEMU 的進程 PID 保存到指定檔案中 | - |
| `-singlestep` | 單布調試模泥器 | - |
| `-S` | 系統開始時不要啟動 CPU,只有當輸入 `c` 時才繼續 | - |
| `-gdb` <dev\> | 等待 gdb 連接 | 有一個 `-s` 選項,它代表 `-gdb tcp::1234` 連接 |
| `-d` | 將 log 文件輸出到 `/tmp/qemu.log` 中 | 可以使用 `-D <檔案>` 指定 log 的保存 |
| `-enable-kvm` | 支持 KVM | 這個選項只有當我們在編譯時開啟 KVM 的選項才有效 |
| `-no-reboot` | 退出,而不是重啟 | - |
| `-no-shutdown` | 當 guest 關機時,不退穿,只是停止 | - |
### 啟動 QEMU 虛擬機
* 我們這邊使用一個範例:使用 QEMU 創建、加載 Ubuntu 的 iso
1. 到 [**Ubuntu 官方**](https://cn.ubuntu.com/download/desktop) 下載需要的版本的 iso
```shell=
wget https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso
```
2. 使用 QEMU 指令指定映像檔、啟動點
```shell=
# 啟動 x86_64 裝置(虛擬機)
qemu-system-x86_64 \
# 虛擬記憶體設置為 8G
-m 8192 \
# 硬碟啟動
-boot c \
# 新增硬體裝置,並指定 iso 檔案
-drive file=ubuntu-22.04.3-desktop-amd64.iso,format=raw
```
選 `Try or Install Ubuntu` 安裝
> 
進入安裝步驟~
> 
## Android Emulator
Android 模擬器也不是憑空全手動生產出來的,Android 模擬器 **基於 [QEMU](https://github.com/qemu/qemu) 項目**,並對其功能做一些修改
:::info
* Android source 中的 QEMU 源碼主體在 `external/qemu` 資料夾中
:::
### 基礎 指令格式 - 指定啟動
* 必須使用到 emulator 指令,該指令在 `<SDK>/emulator/emulator/` 資料夾下,可將這個資料夾加到 `.bashrc` 中(環境變數中)
```shell=
# 指令格式 1.
emulator -avd <avd_name> [ {-option [value]} … ]
# 指令格式 2.
emulator <@avd_name> [ {-option [value]} … ]
```
兩者個差異只在指定的方式不同,但都一樣 **要指定 avd 裝置的名稱**
> avd 裝置名是 `emulator` 必須的參數
```shell=
# 查看其他使用
emulator -help
```
> 
:::info
* 查看可啟動的 AVD 裝置
```shell=
emulator -list-avds
```
> 
:::
### Emulator 控制指令
* Android emulator 系統相關設置如下
| Options | 說明 | 補充 |
| - | - | - |
| `-cpu-delay <delay>` | CPU 延遲設置 | `0~1000` |
| `-nojni` | 關閉訊行識 JNI 檢查 | - |
| `-qemu` | 傳遞參數給 QEMU | **該選項 ++必須++ 放置在最後!**(在該選項之後的指令都是傳遞給 QEMU 的) |
| `-gpu <on/off>` | 開關 GPU 圖形加速 | - |
| `-gps <device>` | 重定向 GPS 設備 | 可參考 `-serial-dev` 選項 |
| `-radio <device>` | 重定向到字符設備 | 同上 |
| `-timezone <timezone>` | 設置時區訊息 | - |
* **設定硬碟相關指令**:
| Options | 說明 | 補充 |
| - | - | - |
| `-data <filepath>` | 設置 `user-data` 映像文件 | 如果沒有指定,系統會尋找名為 `userdata-qemu` 映像檔來替代 |
| `-cache <filepath>` | 指定 cache 的分區映像文件 | 如果沒有指定,系統會創建一個臨時文件替代 |
| `-nocache` | 不使用 cache 分區 | - |
| `-ramdisk <filepath>` | 指定 ramdisk 映像文件 |
| `-sdcard <filepath>` | 指定 sdcard 映像文件 |
| `-wipe-data` | 重置 `user-data` |
| `-initdata <filepath>` | 當使用 `-wipe-data` 重置 `user-data` 時,會將設置的文件複製到新的 `user-data` | 如果沒有指定,則複製 `<system>/userdata.img` 值 |
:::info
* **查看**:可以通過兩種方式發現當前模擬器使用那個文件位置作為模擬器的硬碟
```shell=
# 1. 啟動時加上 -verbose or -debug init 就可以查看輸出
emulator -avd testx86 -verbose
# 2.
emulator -help-datadir
```
可以看到預設資料夾為 `/home/aliens/Android/Sdk` 目錄中
> 
:::
* **設定 UI 相關指令**:
| Options | 說明 | 補充 |
| - | - | - |
| `-dpi-device <dpi>` | 設置模擬器的 dpi | 默認為 165 |
| `-no-boot-anim` | 關閉模擬器的啟動動畫 | - |
| `-no-window` | 關閉模擬器視窗(該模式下以指令與模擬器通訊) | - |
| `-noskin` | 不使用模擬器外殼 | |
| `-scale <scale>` | 調整顯示窗口的比率 | `0.1 ~ 3`, `Auto` 代表最佳值 |
* **設定網路相關指令**:
| Options | 說明 | 補充 |
| - | - | - |
| `-dns-server <servers>` | 設置 DNS 伺服器 | - |
| `-http-proxy <proxy>` | 設置 HTTP/HTTPS 代理 | 格式:`http://<server>:<port>` |
| `-netdelay <delay>` | 設置網路延遲,可以用來模擬較差的網路環境 | - |
| `netspeed` | 設置網速 | 選項:gsm, hscsd, sprs, edge, umts, hsdpa, full... 或是自訂 `<num>`, `<up>:<down>` |
| `-netfast` | 相當於 `-netspeed full -netdelay none` | - |
* **設定調適相關指令**:
| Options | 說明 | 補充 |
| - | - | - |
| `-logcat <logtags>` | 讓 log 輸出 | 部分廠商會過濾 logcat 避免影像性能 |
| `-shell` | 創建一個 root 權限的終端 | - |
| `-shell-serial <device>` | 創建一個 root 權限的字符設備來與模擬器通訊 | - |
| `-show-kernel <name>` | 打印內核訊息 | - |
### 連接 Emulator Console 模擬控制台
* Android 系統的每個模擬器都會 **佔用兩個端口**:^1.^ Emulator 與 adb 進行通訊的 Port(基數)、^2.^ Emulator Console 模擬控制台(偶數)
> 下圖為 Emulator Console 佔用的 Port 號 (5554)
>
> 
* **連接 Emulator Console 模擬控制台**
```shell=
# 使用 telnet 與本地裝置通訊
telnet localhost 5554
# ---- 以下進入 Emulator Console ----
#
# 先驗證 auth <~/.emulator_console_auth_token>
auth 123456789ABCdefZ
```
:::info
* Port 號查詢
```shell=
# 使用 adb 查看裝置佔用的 Port 號
adb devices -l
```
:::
> 
:::warning
* 在連接後,首先第一步是驗證 `auth`,如果沒有經過驗證,就無法使用模擬器的所有選項
* 讀取 `~/.emulator_console_auth_token` 文件
* 使用 `telnet` 指令連接上模擬器後,使用上述文件的數值進行驗證
:::
### Emulator Console 控制命令
* 在我們連接上 Emulator Console 後就可以對啟動的模擬器下指令;以下是常用的幾種命令
* **`avd` 相關命令**:模擬器自身狀態的控制
| 命令 | 參數 | 功能概述 |
| - | - | - |
| name | - | 模擬器名稱 |
| status | - | 模擬器狀態 |
| start | - | 繼續運行模擬器(通常在 stop 後使用) |
| stop | - | 將模擬器掛起(並非關閉) |
| kill | - | 關閉模擬器 |
| exit/quit | - | 退出控制台 |
| snapshot | list | 模擬器快照,可用於恢復模擬器某時刻的操作 |
| | save <name\> | |
| | load <name\> | |
| | del <name\> | |
* **`event` 相關命令**:向模擬器發送硬體事件
| 命令 | 參數 | 功能概述 |
| - | - | - |
| types | - | 列出所有支持的假 event 類型 |
| codes | <type\> | 列出指定虛假事件類型的事件代碼 |
| text | <message\> | 發送 message 案件事件流 |
| send | <type\>:<code\>:<value\> | 向模擬器發送指定的事件(**type、code 數值參考上面**) |
```shell=
# 進入 console 對話畫面,下達長按電源按鈕
event send EV_KEY:KEY_POWER:0
event send EV_KEY:KEY_POWER:1
```
> 
* **`geo` 相關命令**:調整 GPS 地址給模擬器
| 命令 | 參數 | 功能概述 |
| - | - | - |
| fix | <經度><緯度>[高度] | 提供 GPS 修正值 |
* **`gsm` 相關命令**:模擬 GSM 通訊(電話、GPRS 數據... 等等)
| 命令 | 參數 | 功能概述 |
| - | - | - |
| call | <電話號碼> | 模擬來電 |
| accept | <電話號碼> | 將通話的狀態切換至「Active」(前提是電話處於 `waiting` or `held`) |
| busy | <電話號碼> | 掛斷電話,切換為「Busy」狀態(前提是電話處於 `waiting` ) |
| cancel | <電話號碼> | 結束一個來電、去電 |
| list | - | 列出當前所有通話、其狀態! |
| data | <state\> | 改變 GPRS 數據連接的狀態,可選值有:`unregustered`(當前無可用網路)、`home`(在 home 網路)、`roaming`(漫遊中)、`searching`(搜尋可用網路)、`denied`(限緊急通話)、`off`(無可用網路,如 unregustered)、`on`(如 home) |
| voice | <state\> | 同 data |
| status | - | 當前 GSM 數據、語音狀態 |
```shell=
gsm call 123456789
gsm list
```
> 
>
> 
* **`network` 相關命令**:模擬器網路相關設定
| 命令 | 參數 | 功能概述 |
| - | - | - |
| status | - | 當前網路狀態(下載、上傳)資訊 |
| speed | <速度> | 動態改變網路速度 |
| delay | <延遲時間> | 單位為 `ms`… 可以設定區間 `<min>:<max>`;無延遲 `none` |
| capture | start <file\> | 開始捕捉網路封包 |
| | stop | 停止捕捉網路封包 |
```shell=
network status
network speed 100
network status
network delay 50
network status
```
> 
* **`power` 相關命令**:模擬器電源 🔌 相關設定
| 命令 | 參數 | 功能概述 |
| - | - | - |
| display | - | 顯示電量、充電情況 |
| ac | `<on>`、`<off>` | 開啟、關閉 AC 充電 |
| status | <`unknow`>、<`charging`>、<`discharging`>、<`notcharging`>、<`full`> | 設定電池狀態 |
| present | `<true>`、`<false>` | 設置電池是否存在 |
| health | `<unknow>`、`<good>`、`<overheat>`、`<dead>`... | 設置電池健康狀態 |
| capacity | <數值> | 電量 |
```shell=
power display
power ac off
power display
power capacity 66
power display
```
> 
* **`redir` 相關命令**:端口轉向相關設定
| 命令 | 參數 | 功能概述 |
| - | - | - |
| list | - | 列出端口重定位 |
| add | <protocol\>:<hostport\>:<guest-port\> | 新增端口轉向 (protocol: `tcp`、`udp`)... |
| del | 刪除端口 | |
| | | |
* **`sms` 相關命令**:短信相關設定
| 命令 | 參數 | 功能概述 |
| - | - | - |
| send | <電話號碼> <信息內容> | 模擬 SMS 訊息 |
| pdu | <hexstring\> | 發送 SMS PDU 包 |
* **`sensor` 相關命令**:感應裝置相關設定
| 命令 | 參數 | 功能概述 |
| - | - | - |
| status | - | 裝置的傳感器的狀態信息 |
| get | <感應裝置名> | 取得感應裝置當前的數值 |
| set | <感應裝置名> <value\> | 設置感應裝置的數值 |
> 
* **`qemu` 相關命令**:
| 命令 | 參數 | 功能概述 |
| - | - | - |
| monitor | - | **進入 qemu monitor 狀態,可以發送 qemu 支持的指令** |
| | | |
| | | |
## [啟動時間](https://developer.android.com/topic/performance/vitals/launch-time?hl=zh-cn#in-this-document)
啟動有分為三種模式,冷、溫、熱啟動,要先了解這三者的差異才可以知道要使用哪種方式啟動
### 冷、溫、熱啟動
1. **冷啟動**:意指**應用從頭開始啟動**,耗用的時間相對來說就比較長
1. 加載並啟動應用
2. 啟動後創建空白頁面(Launch 的空白頁)
3. 創建應用進程
4. 創建應用對象 (Applicatoin#onCreate)
5. 創建 main thread
6. 創建 laumch activity
7. 分析布局並擴充 (onCreate#setContentView)
8. 布局畫面
9. draw
> 
2. **熱啟動**:所有 Activity 仍保留在內存中,不會初始化對象,但內存整理事件會重製(eg. 記憶體檢測 onTrimMemory 就會被清除資料)
3. **溫啟動**:細通將應用從內存中清除,然後重起它,這時 **進程 & Activity 需重新啟動,但 state bundle 則會保存下來**
## 常用指令
### 快速啟動 - snapshot
| 指令 options | 說明 |
| -------- | -------- |
| -no-snapshot-load | 冷啟動,在退出模擬器時保留狀態 |
| -no-snapshot-save | 盡量執行快速啟動,退出時不保留模擬器狀態 |
| -no-snapshot | 停用快速啟動,不會加載 & 保存模擬器狀態 |
```shell=
emulator @A30X86_64 -no-snapshot-load
emulator @A30X86_64 -no-snapshot-save
emulator @A30X86_64 -no-snapshot
```
### 硬體設備
* 在模擬器中,模擬相機的功能
| 指令 options | 說明 |
| -------- | -------- |
| -webcam-list | 列出當前 PC 裝置可使用的相機列表 |
| -camera-back <mode\> | mode: emulated(模擬鏡頭), webcamn(n 請看相機列表的數字決定), non(不啟動) |
| -camera-front <mode\> | 同上 |
### 內存 & 儲存空間
* 內存 & 儲存空間相關設定
| 指令 options | 說明 |
| -------- | -------- |
| -memory <size\> | 物理記憶體大小範圍從 128MB 到 4096 MB |
| -sdcard <filepath\> | avd SD 卡映射的路徑 |
| -wipt-data | 清除該模擬器的數據,回歸到最初設定的狀態|
:::info
* 默認情況下,用戶數據文件是 `userdata-qemu.img`,最終數據文件是 `userdata.img`,這兩個文件都在數據目錄中
`-wipe-data` 選項不會影響 sdcard img 文件。如需詳細了解用戶數據,請參閱了解默認目錄和文件。
:::
### Debug 調適
* Debug 調適相關設置
| 指令 options | 說明 |
| -------- | -------- |
| -debug <tags\> | **tags 可以透過 -help-debug-tags 查詢**,可以過濾訊息,若是不需要的訊息可以使用 `,-` 過濾 |
| -debug-<tag\> | 指接收 tag 類型的訊息 |
| -debug-no-<tag\> | 不需要 tag 類型的訊息 |
| -logcat <logtags\> | **logtags 與 adb logcat 的指令格式相同** |
| -show-kernel | 內核訊息 |
| -verbose | 輸出詳細訊息,與 -debug-init 相同效果 |
```shell=
emulator -help-debug-tags
```
> 
```shell=
# 查看 init 相關訊息
emulator @A30X86_64 -debug init
# 功能同上
emulator @A30X86_64 -debug-init
# 查看所有訊息,除了 init & socket 訊息
emulator @A30X64_64 -debug all,-socket,-init
```
* **logtags 使用與 adb logcat logtags 命令相同的格式(輸入 adb logcat -help 可了解詳情)**;它是 componentName:logLevel 格式的以刪除或刪除請求的日誌過濾器列表。componentName 是星號通配符 (\*) 或組件名稱 ,如 `ActivityManager`、`SystemServer`、`InputManager`、`WindowManager` 等;logLevel 是以下值之一:
| logLevel | 概述 |
| - | - |
| v | 詳細 |
| d | 調試 |
| i | 信息 |
| w | 警告級別 |
| e | 錯誤 |
| s | 靜默 |
```shell=
emulator @A30X86_64 -logcat '*:s ActivityManager:i'
```
### 網路
* 網路相關設置
| 指令 options | 說明 |
| -------- | -------- |
| -netdelay <dalay\> | dalay 以 ms 為單位,模擬網路延遲 |
| -netfast | 停用網路節流 |
| -netspeed <speed\> | speed 以 KB 為單位 |
## 啟動 ADB 問題
首先先確定一下當前裝置是否有 **CPU 有虛擬化的技術**
```shell=
# 查看 cpuinfo 檔案
egrep -c '(vmx|svm)' /proc/cpuinfo
```
> 
### AMD CPU + Ubuntu 嘗試
* 有碰到一個狀況,**每次啟動 ADB 模擬器,電腦都會死機(鍵盤滑鼠不可動、畫面卡住、但音樂有聲音)**
* 有做過以下嘗試,並得到以下資訊
1. **CPU 資訊**:查看是 cpu 架構使用對應 ABI,但結果還是不行,不管 abi 是 x86, x86_64, armv7a...
```shell=
# 在 Ubuntu 中查看 CPU 型號
lscpu
```
> 
2. **使用 Genymotion 模擬器**:可以 參考 Genymotion 使用,該模擬器要安裝 [**virtual Box**](https://www.virtualbox.org/wiki/Linux_Downloads),但結果還是不行
```shell=
# 參考 1.
https://manatee168.pixnet.net/blog/post/255479221
# 參考 2.
http://cyutin888.blogspot.com/2017/10/ubuntuandroidgenymotion.html
```
3. 使用 KVM 模擬器,結果也不可行
```shell=
# 參考
https://blog.csdn.net/lj402159806/article/details/53967339
# 安裝 KVM 參考
https://ubuntuqa.com/zh-tw/article/9834.html
```
### AMD CPU + Ubuntu 成功
* 最後發現是顯示卡驅動的問題,必須要選用顯示卡專用的驅動,搜尋軟體與更新 -> 額外驅動程式 -> **選擇顯示卡的驅動**

> 
```shell=
# 使用指令開啟 Avd
# 開啟 x86_64 的 Avd device
emulator @A30X86_64 &
```
* 終於啟動成功拉!!!
> 
### Window 子系統 - Qt 異常 (尚未解決)
* 目前情況是已經確定,有透過 avdmanger 安裝好模擬器,但是無法啟動正常 (異常: Could not load the Qt platform plugin)
> 
* 使用 ldd 指令檢查 `libqxcb` 是否有 library 尚未連結,若有尚未連結的則需將尚未連結的 so 放置到 `/usr/lib/x86_64-linux-gnu/` 目錄下
```shell=
# 複製 emulator/lib64/qt/lib/ 目錄下所有 os
cp -a $ANDROID_HOME/emulator/lib64/qt/lib/. /usr/lib/x86_64-linux-gnu/
```
> 
:::info
* 如果是不需要螢幕的啟動,可以輸入以下命令
```shell=
# 無螢幕啟動是正常的
emulator -avd ubuntuAndroid -no-audio -no-boot-anim -no-window -accel on -gpu off &
```
:::
## Appendix & FAQ
:::info
:::
###### tags: `Android 工具` `使用問題`