Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28e937ec authored by Felipe Leme's avatar Felipe Leme
Browse files

Added option to dump a11y state on WM

Test: adb shell dumpsys window -h | grep a11y
Test: adb shell dumpsys window a11y
Test: adb shell dumpsys window accessibility

Bug: 271188189

Change-Id: I64f4bbf13ab6a1b32b880db39f7ed83219e4e1ac
parent 99df8fc9
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -206,6 +206,7 @@ public final class InputWindowHandle {
                .append(", scaleFactor=").append(scaleFactor)
                .append(", scaleFactor=").append(scaleFactor)
                .append(", transform=").append(transform)
                .append(", transform=").append(transform)
                .append(", windowToken=").append(windowToken)
                .append(", windowToken=").append(windowToken)
                .append(", displayId=").append(displayId)
                .append(", isClone=").append((inputConfig & InputConfig.CLONE) != 0)
                .append(", isClone=").append((inputConfig & InputConfig.CLONE) != 0)
                .toString();
                .toString();


+8 −9
Original line number Original line Diff line number Diff line
@@ -44,6 +44,8 @@ import static com.android.server.accessibility.AccessibilityTraceProto.WHERE;
import static com.android.server.accessibility.AccessibilityTraceProto.WINDOW_MANAGER_SERVICE;
import static com.android.server.accessibility.AccessibilityTraceProto.WINDOW_MANAGER_SERVICE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.dumpSparseArray;
import static com.android.server.wm.WindowManagerService.dumpSparseArrayValues;
import static com.android.server.wm.WindowTracing.WINSCOPE_EXT;
import static com.android.server.wm.WindowTracing.WINSCOPE_EXT;


import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.AccessibilityTrace;
@@ -542,15 +544,12 @@ final class AccessibilityController {
    }
    }


    void dump(PrintWriter pw, String prefix) {
    void dump(PrintWriter pw, String prefix) {
        for (int i = 0; i < mDisplayMagnifiers.size(); i++) {
        dumpSparseArray(pw, prefix, mDisplayMagnifiers, "magnification display",
            final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.valueAt(i);
                (index, key) -> pw.printf("%sDisplay #%d:", prefix + "  ", key),
            if (displayMagnifier != null) {
                dm -> dm.dump(pw, ""));
                displayMagnifier.dump(pw, prefix
        dumpSparseArrayValues(pw, prefix, mWindowsForAccessibilityObserver,
                        + "Magnification display# " + mDisplayMagnifiers.keyAt(i));
                "windows for accessibility observer");
            }
        mAccessibilityWindowsPopulator.dump(pw, prefix);
        }
        pw.println(prefix
                + "mWindowsForAccessibilityObserver=" + mWindowsForAccessibilityObserver);
    }
    }


    void onFocusChanged(InputTarget lastTarget, InputTarget newTarget) {
    void onFocusChanged(InputTarget lastTarget, InputTarget newTarget) {
+33 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package com.android.server.wm;
package com.android.server.wm;


import static com.android.server.wm.WindowManagerService.ValueDumper;
import static com.android.server.wm.WindowManagerService.dumpSparseArray;
import static com.android.server.wm.utils.RegionUtils.forEachRect;
import static com.android.server.wm.utils.RegionUtils.forEachRect;


import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -39,7 +41,9 @@ import android.view.WindowManager;
import android.window.WindowInfosListener;
import android.window.WindowInfosListener;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.server.wm.WindowManagerService.KeyDumper;


import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
@@ -562,6 +566,35 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
        notifyWindowsChanged(displayIdsForWindowsChanged);
        notifyWindowsChanged(displayIdsForWindowsChanged);
    }
    }


    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.println("AccessibilityWindowsPopulator");
        String prefix2 = prefix + "  ";

        pw.print(prefix2); pw.print("mWindowsNotificationEnabled: ");
        pw.println(mWindowsNotificationEnabled);

        if (mVisibleWindows.isEmpty()) {
            pw.print(prefix2); pw.println("No visible windows");
        } else {
            pw.print(prefix2); pw.print(mVisibleWindows.size());
            pw.print(" visible windows: "); pw.println(mVisibleWindows);
        }
        KeyDumper noKeyDumper = (i, k) -> {}; // display id is already shown on value;
        KeyDumper displayDumper = (i, d) -> pw.printf("%sDisplay #%d: ", prefix, d);
        // Ideally magnificationSpecDumper should use spec.dump(pw), but there is no such method
        ValueDumper<MagnificationSpec> magnificationSpecDumper = spec -> pw.print(spec);

        dumpSparseArray(pw, prefix2, mDisplayInfos, "display info", noKeyDumper, d -> pw.print(d));
        dumpSparseArray(pw, prefix2, mInputWindowHandlesOnDisplays, "window handles on display",
                displayDumper, list -> pw.print(list));
        dumpSparseArray(pw, prefix2, mMagnificationSpecInverseMatrix, "magnification spec matrix",
                noKeyDumper, matrix -> matrix.dump(pw));
        dumpSparseArray(pw, prefix2, mCurrentMagnificationSpec, "current magnification spec",
                noKeyDumper, magnificationSpecDumper);
        dumpSparseArray(pw, prefix2, mPreviousMagnificationSpec, "previous magnification spec",
                noKeyDumper, magnificationSpecDumper);
    }

    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void releaseResources() {
    private void releaseResources() {
        mInputWindowHandlesOnDisplays.clear();
        mInputWindowHandlesOnDisplays.clear();
+75 −3
Original line number Original line Diff line number Diff line
@@ -235,6 +235,7 @@ import android.util.EventLog;
import android.util.MergedConfiguration;
import android.util.MergedConfiguration;
import android.util.Pair;
import android.util.Pair;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.TimeUtils;
@@ -6697,9 +6698,8 @@ public class WindowManagerService extends IWindowManager.Stub


        mInputManagerCallback.dump(pw, "  ");
        mInputManagerCallback.dump(pw, "  ");
        mSnapshotController.dump(pw, " ");
        mSnapshotController.dump(pw, " ");
        if (mAccessibilityController.hasCallbacks()) {

            mAccessibilityController.dump(pw, "  ");
        dumpAccessibilityController(pw, /* force= */ false);
        }


        if (dumpAll) {
        if (dumpAll) {
            final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
            final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
@@ -6736,6 +6736,23 @@ public class WindowManagerService extends IWindowManager.Stub
        }
        }
    }
    }


    private void dumpAccessibilityController(PrintWriter pw, boolean force) {
        boolean hasCallbacks = mAccessibilityController.hasCallbacks();
        if (!hasCallbacks && !force) {
            return;
        }
        if (!hasCallbacks) {
            pw.println("AccessibilityController doesn't have callbacks, but printing it anways:");
        } else {
            pw.println("AccessibilityController:");
        }
        mAccessibilityController.dump(pw, "  ");
    }

    private void dumpAccessibilityLocked(PrintWriter pw) {
        dumpAccessibilityController(pw, /* force= */ true);
    }

    private boolean dumpWindows(PrintWriter pw, String name, boolean dumpAll) {
    private boolean dumpWindows(PrintWriter pw, String name, boolean dumpAll) {
        final ArrayList<WindowState> windows = new ArrayList();
        final ArrayList<WindowState> windows = new ArrayList();
        if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
        if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
@@ -6855,6 +6872,7 @@ public class WindowManagerService extends IWindowManager.Stub
                pw.println("    d[isplays]: active display contents");
                pw.println("    d[isplays]: active display contents");
                pw.println("    t[okens]: token list");
                pw.println("    t[okens]: token list");
                pw.println("    w[indows]: window list");
                pw.println("    w[indows]: window list");
                pw.println("    a11y[accessibility]: accessibility-related state");
                pw.println("    package-config: installed packages having app-specific config");
                pw.println("    package-config: installed packages having app-specific config");
                pw.println("    trace: print trace status and write Winscope trace to file");
                pw.println("    trace: print trace status and write Winscope trace to file");
                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
@@ -6918,6 +6936,11 @@ public class WindowManagerService extends IWindowManager.Stub
                    dumpWindowsLocked(pw, true, null);
                    dumpWindowsLocked(pw, true, null);
                }
                }
                return;
                return;
            } else if ("accessibility".equals(cmd) || "a11y".equals(cmd)) {
                synchronized (mGlobalLock) {
                    dumpAccessibilityLocked(pw);
                }
                return;
            } else if ("all".equals(cmd)) {
            } else if ("all".equals(cmd)) {
                synchronized (mGlobalLock) {
                synchronized (mGlobalLock) {
                    dumpWindowsLocked(pw, true, null);
                    dumpWindowsLocked(pw, true, null);
@@ -9429,4 +9452,53 @@ public class WindowManagerService extends IWindowManager.Stub
            return List.copyOf(notifiedApps);
            return List.copyOf(notifiedApps);
        }
        }
    }
    }

    // TODO(b/271188189): move dump stuff below to common code / add unit tests

    interface ValueDumper<T> {
        void dump(T value);
    }

    interface KeyDumper{
        void dump(int index, int key);
    }

    static void dumpSparseArray(PrintWriter pw, String prefix, SparseArray<?> array, String name) {
        dumpSparseArray(pw, prefix, array, name, /* keyDumper= */ null, /* valuedumper= */ null);
    }

    static <T> void dumpSparseArrayValues(PrintWriter pw, String prefix, SparseArray<T> array,
            String name) {
        dumpSparseArray(pw, prefix, array, name, (i, k) -> {}, /* valueDumper= */ null);
    }

    static <T> void dumpSparseArray(PrintWriter pw, String prefix, SparseArray<T> array,
            String name, @Nullable KeyDumper keyDumper, @Nullable ValueDumper<T> valueDumper) {
        int size = array.size();
        if (size == 0) {
            pw.print(prefix); pw.print("No "); pw.print(name); pw.println("s");
            return;
        }
        pw.print(prefix); pw.print(size); pw.print(' ');
        pw.print(name); pw.print(size > 1 ? "s" : ""); pw.println(':');

        String prefix2 = prefix + "  ";
        for (int i = 0; i < size; i++) {
            int key = array.keyAt(i);
            T value = array.valueAt(i);
            if (keyDumper != null) {
                keyDumper.dump(i, key);
            } else {
                pw.print(prefix2); pw.print(i); pw.print(": "); pw.print(key); pw.print("->");
            }
            if (value == null) {
                pw.print("(null)");
            } else if (valueDumper != null) {
                valueDumper.dump(value);
            } else {
                pw.print(value);
            }
            pw.println();
        }
    }
}
}