2

我正在尝试列出 Android 设备上显示的所有 UI 元素。我通过在 adb shell 中运行“dumpsys window windows | grep “Window #”来做到这一点。这给了我一个从窗口 n 到 0 的窗口列表。

我想知道输出顺序是如何确定的。窗口 n 在栈顶,窗口 0 在栈底吗?另外,这些字段是什么意思?例如第一行显示如下

Window #64 Window{793212d u0 NavigationBar}:

值 793212d 和 u0 表示什么?

4

1 回答 1

3

关于输出顺序:

  • 窗口按 z 顺序从上到下遍历,因此最顶层的窗口首先出现。

关于字段:

  • 793212d是窗口的(唯一)ID,使用System #identityHashCode获得。

  • u0指的是窗口所属的用户ID 用户 id 与 Unix UID 不同,它是一个更高级的概念。Android 将多个 Unix UID 分组为属于一个用户 ID,即前 100.000 个 Unix UID 属于用户 ID 0,依此类推(参考)。为了确定窗口的用户 ID,Android 会查找窗口的 Unix UID(每个应用程序都有自己的 Unix UID),然后将 Unix UID 映射到用户 ID。

  • NavigationBar是窗口的标题。

技术细节:调用时,会在(链接dumpsys window windows处触发转储请求。此类有一个type 的成员,转储请求将被转发到该成员(链接)。相关代码为:WindowManagerServicemRootRootWindowContainer

        forAllWindows((w) -> {
            if (windows == null || windows.contains(w)) {
                pw.println("  Window #" + index[0] + " " + w + ":");
                w.dump(pw, "    ", dumpAll || windows != null);
                index[0] = index[0] + 1;
            }
        }, true /* traverseTopToBottom */);

wis 类型WindowState,它覆盖toString以获得您在输出(链接String中看到的表示。相关代码为:dumpsys

mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
    + " u" + UserHandle.getUserId(mOwnerUid)
    + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");

RootWindowContainer#forAllWindows方法遍历mChildren列表,该列表指定为 z 顺序(链接链接):

    // List of children for this window container. List is in z-order as the children appear on
    // screen with the top-most window container at the tail of the list.
    protected final WindowList<E> mChildren = new WindowList<E>();
    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
        if (traverseTopToBottom) {
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
                    return true;
                }
            }
        ...
于 2020-07-01T18:55:23.600 回答