ByteScope

dumpsys activity activities

唯讀

現在哪個 app 在前景,以及它背後的 task 與 stack 結構。

指令
adb shell dumpsys activity activities
指令
系統服務(dumpsys)
風險
唯讀

語法

dumpsys activity activities

範例

  • dumpsys activity activities | grep -E 'topResumedActivity|mResumedActivity' | head -n 12

    只取出前景元件。在裝置上先過濾,是把傳輸量壓小的關鍵。

  • dumpsys activity activities

    整份。在醒了一段時間的手機上大約是一百 KB。

輸出怎麼讀

完整的輸出會印出每個顯示器上每個 stack 裡的每個 task,所以請先過濾。有四種行都在回答「現在前面是什麼」,而它們不一定一致:優先用 `topResumedActivity`,因為那就是這個問題本身;把 `mCurrentFocus` 當成最後手段,因為它指的是「視窗」,而那可能是鍵盤或系統對話框,後面那個 app 對使用者來說才是他正在用的 app。

輸出欄位

欄位意義
topResumedActivity=唯一處於 top-resumed 狀態的 Activity。Android 10 之後才有。
mResumedActivity: / ResumedActivity:某個 stack 的 resumed Activity。可能出現好幾行,通常第一行是答案。
mFocusedApp=取得焦點的 app token。實務上是對的,只差一層間接。
mCurrentFocus=取得焦點的視窗——可能是輸入法或對話框而不是 app。
u0 com.example/.MainActivityAndroid 使用者 id 加元件。元件常寫成相對於套件的形式。

需要什麼權限

`ActivityManagerService.doDump` 一開頭就用標籤 `ActivityManager` 呼叫 `DumpUtils.checkDumpAndUsageStatsPermission`,所以要 `android.permission.DUMP` 加上 `android.permission.PACKAGE_USAGE_STATS`,兩個都由 Shell 套件宣告,而 `SHELL_UID` 會讓 app-op 那道檢查直接短路。條件就這樣:不用 root、不用 `adb root`、不用無障礙服務,也不用在設定裡給「使用情況存取權」——這也是為什麼「讀出前景 app」是纜線在什麼都不解鎖的情況下,少數幾件看起來很特權的事。shell 拿不到的,是讓它變便宜的方法。用 `grep` 過濾是在 `system_server` 已經把整份 dump 組完之後才篩,所以手機上的工作量兩種寫法完全一樣,你省下的只有傳輸。還有一件參數解析會做、而且沒有任何權限保護得了你的事:當 `activity` 後面那個字不是它認得的段落時,這份 dump 會先拿去比對執行中的 Activity,比不到就把**整串參數交給 activity manager 的 shell 指令直譯器去執行**。所以 `dumpsys activity <某個字>` 並不保證是唯讀的。把 `activities` 這個字原封不動打對,或改用 Android System Monitor,它只送出那個過濾過的讀取形式。

失敗訊息對照

訊息意義
Bad activity command, or no activities match: activites印在標準輸出,後面接著 `Use -h for help.`,而在那之前已經試過三件事:這個字不是已知的段落、對不上任何執行中的 Activity,然後它被當成 activity manager 的 shell 指令執行了、而且回報失敗。打錯字在這裡之所以無害,只是因為那個 shell 指令也失敗了——一個剛好拼成某個真子指令的打錯,就不是打錯,那是一道指令。
Unknown argument: --activities; use -h for help選項是有連字號前綴的那些;`activities` 是指令不是選項,所以加了連字號寫就會掉進選項迴圈。和套件管理員那個版本不同,activity 的 dump 印完這行就**立刻返回**,所以你只會拿到這一行而不是一份預設 dump——至少這讓錯誤很明顯。
Permission Denial: can't dump ActivityManager from from pid=4821, uid=10231 due to missing android.permission.DUMP permission來自 `DumpUtils`,帶著那個確實是 AOSP 原文的重複 `from from`,寫在**標準輸出**、取代整份 dump。把它接進一個 `grep topResumedActivity` 就會無聲無息地消失,而結果和一台螢幕關著的手機分不出來。前景 app 的查詢回空的時候,去看沒有過濾的第一行。
*** SERVICE 'activity' DUMP TIMEOUT (10000ms) EXPIRED ***截斷在這裡比多數 dump 更要緊。resumed activity 那幾行不在輸出的最前面,所以一份在十秒被切掉的 dump 可能弄丟 `topResumedActivity`,卻還留著大量 task 與 stack 的文字——讀起來會像「前景什麼都沒有」,而不是像一個不完整的答案。先用 `-t` 拉長等待,再考慮退而求其次去看 `mCurrentFocus` 這種比較弱的行。

版本與廠商注意事項

  • 這裡的欄位名稱改過兩次,也被複製到別的服務裡,所以要比對一組拼法而不是單一拼法。
  • 不論你有沒有過濾,binder 的工作都在手機上發生;過濾省下的是傳輸,而在纜線上那才是隨輸出大小成長的部分。

這個我們有 UI

Android System Monitor 會透過 USB 執行這個指令並解析回應——只要 Chromium 系瀏覽器,不必安裝 SDK,也不會上傳任何東西。

開啟 Android System Monitor

相關指令

和 dumpsys activity activities 會在同一次作業裡出現的指令。

指令做什麼
am start用元件或 intent 啟動 Activity——這是驗證 deep link 能不能被接走最快的方法。
am force-stop殺掉屬於某個 app 的所有行程與服務。
top一次性的行程表:CPU 占用、記憶體、狀態與指令列。

其他系統服務(dumpsys)指令

指令做什麼
dumpsys battery電池服務目前的狀態:電量、充電狀態、健康度、電壓與溫度。
dumpsys diskstats每個分割區的剩餘空間、一次磁碟寫入延遲的實測,以及一份快取起來的各 app 空間用量。
dumpsys thermalservice手機是不是正在因為溫度而降速,以及硬體層回報的每一個溫區,單位是攝氏。
dumpsys sensorservice手機上的每一個感測器,含廠商、type、取樣率與批次能力,以及一段近期讀數的緩衝。
dumpsys meminfo哪些行程最吃記憶體,量的是 PSS(按比例分攤的用量)。
dumpsys package套件管理員知道的一切:版本、路徑、flags、安裝來源,以及每個使用者的狀態。
dumpsys dropbox平台用來存放當機、ANR 與 tombstone 的環形緩衝——這是不用 root 讀 ANR 追蹤的方法。

這些行為是在撰寫 Web ADB 工具背後的解析程式時,對照 AOSP、toybox 與核心原始碼查證的。真的會因 Android 版本或廠牌而異的地方,這一頁會直接說明,而不是給你一個在半數手機上都是錯的數字。

常見問題

adb shell 指令要怎麼執行?

在手機上打開開發者選項與 USB 除錯、接上線,然後從裝了 platform-tools 的機器執行 adb shell <指令>——或者只執行 adb shell 取得互動提示字元,再直接打指令、不用前綴。如果指令會輸出二進位資料(例如截圖),請改用 adb exec-out 而不是 adb shell:單純的 shell 服務會配一個終端機,而它會改寫換行位元組並毀掉資料。

adb shell 指令需要 root 嗎?

這份參考裡的都不用。它們以 shell 使用者身分執行,可以針對自己的 Android 使用者管理套件、讀取大多數 dumpsys 服務、寫入設定提供者、注入輸入,以及讀取共用儲存空間。需要 root 的是這份參考刻意避開的事:讀取其他 app 的私有資料(除了對可除錯版本使用 run-as)、寫入系統分割區,或直接讀 /data/anr。

為什麼在我的手機上輸出看起來不一樣?

不是 Android 版本就是廠商。有些旗標與欄位是從特定版本才有的,那些都在各指令頁註明了。其餘是廠商改動,而受影響最深的是 dumpsys:一份 dump 是除錯輸出,它的文字就是那個服務的作者最後印了什麼,而廠商既會改它也會把改動往回移植。請用名稱而不是位置來讀欄位,並把沒見過的格式當成差異而不是失敗。

可以用瀏覽器而不是終端機來跑嗎?

很多指令可以——本站的 Web ADB 工具從 Chromium 系桌面瀏覽器透過 WebUSB 和手機對話,不必安裝 SDK,也不會上傳任何東西。每一頁在有對應工具時都會連過去。有兩個限制值得知道:同一時間只有一個程式能持有 ADB 介面,所以桌面的 adb server 要先停掉;而 adb forward 與 adb reverse 在瀏覽器裡完全無法運作。

比較想按而不是打字?Web ADB Toolkit 會從瀏覽器透過 USB 執行這類指令。或者瀏覽全部指令。