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

Commit cccfbd7e authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Re-order InputMethodManagerService state dump

With the changes in [1] to enable dumping the state for concurrent
multi-users, some of the dumps were re-ordered, leading to some state
being dumped after the InputMethodService dump is called. The issue is
that IMEs can override the dump method to include their own state with
an unknown number of arguments. This leads to the system state being
pushed all the way to the end of the dump.

This introduces a dumping order similar to the one before [1],
additionally fixes some mismatching in the prefix whitespace,
and introduces some missing state in the dumps.

  [1]: I604784d6cb637334d933d20890998daa29181849

Flag: EXEMPT state dump
Bug: 356239178
Test: presubmit
Change-Id: Iacf9ef9f8293d5d7656505906baa7889a1a3f90d
parent 3f4654f4
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.server.inputmethod.InputMethodManagerServiceProto.CUR_FOCU
import static android.server.inputmethod.InputMethodManagerServiceProto.CUR_FOCUSED_WINDOW_SOFT_INPUT_MODE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.os.IBinder;
@@ -86,10 +87,10 @@ final class ImeBindingState {
                InputMethodDebug.softInputModeToString(mFocusedWindowSoftInputMode));
    }

    void dump(String prefix, Printer p) {
        p.println(prefix + "mFocusedWindow()=" + mFocusedWindow);
        p.println(prefix + "softInputMode=" + InputMethodDebug.softInputModeToString(
                mFocusedWindowSoftInputMode));
    void dump(@NonNull Printer p, @NonNull String prefix) {
        p.println(prefix + "mFocusedWindow=" + mFocusedWindow);
        p.println(prefix + "mFocusedWindowSoftInputMode="
                + InputMethodDebug.softInputModeToString(mFocusedWindowSoftInputMode));
        p.println(prefix + "mFocusedWindowClient=" + mFocusedWindowClient);
    }

+95 −96
Original line number Diff line number Diff line
@@ -6063,27 +6063,31 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.

    @BinderThread
    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @Nullable String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;

        PriorityDump.dump(mPriorityDumper, fd, pw, args);
    }

    @BinderThread
    private void dumpAsStringNoCheck(FileDescriptor fd, PrintWriter pw, String[] args,
            boolean isCritical) {
    private void dumpAsStringNoCheck(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
            @NonNull String[] args, boolean isCritical) {
        final int argUserId = parseUserIdFromDumpArgs(args);
        final Printer p = new PrintWriterPrinter(pw);
        p.println("Current Input Method Manager state:");
        p.println("Input Method Manager Service state:");
        p.println("  mSystemReady=" + mSystemReady);
        p.println("  mInteractive=" + mIsInteractive);
        p.println("  mConcurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled);
        p.println("  ENABLE_HIDE_IME_CAPTION_BAR="
                + InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR);
        final int currentImeUserId;
        synchronized (ImfLock.class) {
            currentImeUserId = mCurrentImeUserId;
            p.println("  mCurrentImeUserId=" + currentImeUserId);
            p.println("  mStylusIds=" + (mStylusIds != null
                    ? Arrays.toString(mStylusIds.toArray()) : ""));
        }
        // TODO(b/305849394): Make mMenuController multi-user aware.
        if (Flags.imeSwitcherRevamp()) {
            p.println("  mMenuControllerNew:");
            mMenuControllerNew.dump(p, "    ");
@@ -6091,14 +6095,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            p.println("  mMenuController:");
            mMenuController.dump(p, "    ");
        }
        if (mConcurrentMultiUserModeEnabled && argUserId == UserHandle.USER_NULL) {
            mUserDataRepository.forAllUserData(
                    u -> dumpAsStringNoCheckForUser(u, fd, pw, args, isCritical));
        } else {
            final int userId = argUserId != UserHandle.USER_NULL ? argUserId : mCurrentImeUserId;
            final var userData = getUserData(userId);
            dumpAsStringNoCheckForUser(userData, fd, pw, args, isCritical);
        }
        dumpClientController(p);
        dumpUserRepository(p);

        // TODO(b/365868861): Make StartInputHistory and ImeTracker multi-user aware.
        synchronized (ImfLock.class) {
@@ -6112,12 +6110,18 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        p.println("  mImeTrackerService#History:");
        mImeTrackerService.dump(pw, "    ");

        dumpUserRepository(p);
        dumpClientStates(p);
        if (mConcurrentMultiUserModeEnabled && argUserId == UserHandle.USER_NULL) {
            mUserDataRepository.forAllUserData(
                    u -> dumpAsStringNoCheckForUser(u, fd, pw, args, isCritical));
        } else {
            final int userId = argUserId != UserHandle.USER_NULL ? argUserId : currentImeUserId;
            final var userData = getUserData(userId);
            dumpAsStringNoCheckForUser(userData, fd, pw, args, isCritical);
        }
    }

    @UserIdInt
    private static int parseUserIdFromDumpArgs(String[] args) {
    private static int parseUserIdFromDumpArgs(@NonNull String[] args) {
        final int userIdx = Arrays.binarySearch(args, "--user");
        if (userIdx == -1 || userIdx == args.length - 1) {
            return UserHandle.USER_NULL;
@@ -6127,30 +6131,22 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.

    // TODO(b/356239178): Update dump format output to better group per-user info.
    @BinderThread
    private void dumpAsStringNoCheckForUser(UserData userData, FileDescriptor fd, PrintWriter pw,
            String[] args, boolean isCritical) {
    private void dumpAsStringNoCheckForUser(@NonNull UserData userData, @NonNull FileDescriptor fd,
            @NonNull PrintWriter pw, @NonNull String[] args, boolean isCritical) {
        final Printer p = new PrintWriterPrinter(pw);
        IInputMethodInvoker method;
        ClientState client;
        IInputMethodInvoker method;
        p.println("  UserId=" + userData.mUserId);
        synchronized (ImfLock.class) {
            final InputMethodSettings settings = InputMethodSettingsRepository.get(
                    userData.mUserId);
            final List<InputMethodInfo> methodList = settings.getMethodList();
            int numImes = methodList.size();
            p.println("    Input Methods:");
            for (int i = 0; i < numImes; i++) {
                InputMethodInfo info = methodList.get(i);
                p.println("      InputMethod #" + i + ":");
                info.dump(p, "        ");
            }
            final var bindingController = userData.mBindingController;
            p.println("        mCurMethodId=" + bindingController.getSelectedMethodId());
            client = userData.mCurClient;
            method = bindingController.getCurMethod();
            p.println("    mCurMethodId=" + bindingController.getSelectedMethodId());
            p.println("    mCurClient=" + client + " mCurSeq="
                    + bindingController.getSequenceNumber());
            p.println("    mFocusedWindowPerceptible=" + mFocusedWindowPerceptible);
            userData.mImeBindingState.dump(/* prefix= */ "  ", p);
            p.println("    mImeBindingState:");
            userData.mImeBindingState.dump(p, "      ");
            p.println("    mCurId=" + bindingController.getCurId());
            p.println("    mHaveConnection=" + bindingController.hasMainConnection());
            p.println("    mBoundToMethod=" + userData.mBoundToMethod);
@@ -6159,12 +6155,22 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            p.println("    mCurTokenDisplayId=" + bindingController.getCurTokenDisplayId());
            p.println("    mCurHostInputToken=" + bindingController.getCurHostInputToken());
            p.println("    mCurIntent=" + bindingController.getCurIntent());
            method = bindingController.getCurMethod();
            p.println("    mCurImeWindowVis=" + bindingController.getImeWindowVis());
            p.println("    mCurMethod=" + method);
            p.println("    mEnabledSession=" + userData.mEnabledSession);
            final var visibilityStateComputer = userData.mVisibilityStateComputer;
            visibilityStateComputer.dump(pw, "  ");
            p.println("    mVisibilityStateComputer:");
            userData.mVisibilityStateComputer.dump(pw, "      ");
            p.println("    mInFullscreenMode=" + userData.mInFullscreenMode);

            final var settings = InputMethodSettingsRepository.get(userData.mUserId);
            final List<InputMethodInfo> methodList = settings.getMethodList();
            final int numImes = methodList.size();
            p.println("    Input Methods:");
            for (int i = 0; i < numImes; i++) {
                final InputMethodInfo info = methodList.get(i);
                p.println("      InputMethod #" + i + ":");
                info.dump(p, "        ");
            }
        }

        // Exit here for critical dump, as remaining sections require IPCs to other processes.
@@ -6184,18 +6190,16 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            p.println("No input method client.");
        }
        synchronized (ImfLock.class) {
            if (userData.mImeBindingState.mFocusedWindowClient != null
                    && client != userData.mImeBindingState.mFocusedWindowClient) {
            final var focusedWindowClient = userData.mImeBindingState.mFocusedWindowClient;
            if (focusedWindowClient != null && client != focusedWindowClient) {
                p.println("");
                p.println("Warning: Current input method client doesn't match the last focused. "
                p.println("Warning: Current input method client doesn't match the last focused"
                        + " window.");
                p.println("Dumping input method client in the last focused window just in case.");
                p.println("");
                pw.flush();
                try {
                    TransferPipe.dumpAsync(
                            userData.mImeBindingState.mFocusedWindowClient.mClient.asBinder(), fd,
                            args);
                    TransferPipe.dumpAsync(focusedWindowClient.mClient.asBinder(), fd, args);
                } catch (IOException | RemoteException e) {
                    p.println("Failed to dump input method client in focused window: " + e);
                }
@@ -6215,16 +6219,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        }
    }

    private void dumpClientStates(Printer p) {
        p.println(" ClientStates:");
    private void dumpClientController(@NonNull Printer p) {
        p.println("  mClientController:");
        // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
        @SuppressWarnings("GuardedBy") Consumer<ClientState> clientControllerDump = c -> {
            p.println("    " + c + ":");
            p.println("      client=" + c.mClient);
            p.println("    fallbackInputConnection="
                    + c.mFallbackInputConnection);
            p.println("    sessionRequested="
                    + c.mSessionRequested);
            p.println("      fallbackInputConnection=" + c.mFallbackInputConnection);
            p.println("      sessionRequested=" + c.mSessionRequested);
            p.println("      sessionRequestedForAccessibility="
                    + c.mSessionRequestedForAccessibility);
            p.println("      curSession=" + c.mCurSession);
@@ -6237,15 +6239,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        }
    }

    private void dumpUserRepository(Printer p) {
        p.println("  mUserDataRepository=");
    private void dumpUserRepository(@NonNull Printer p) {
        p.println("  mUserDataRepository:");
        // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
        @SuppressWarnings("GuardedBy") Consumer<UserData> userDataDump =
                u -> {
                    p.println("    mUserId=" + u.mUserId);
        @SuppressWarnings("GuardedBy") Consumer<UserData> userDataDump = u -> {
            p.println("    userId=" + u.mUserId);
            p.println("      unlocked=" + u.mIsUnlockingOrUnlocked.get());
                    p.println("      hasMainConnection="
                            + u.mBindingController.hasMainConnection());
            p.println("      hasMainConnection=" + u.mBindingController.hasMainConnection());
            p.println("      isVisibleBound=" + u.mBindingController.isVisibleBound());
            p.println("      boundToMethod=" + u.mBoundToMethod);
            p.println("      curClient=" + u.mCurClient);
@@ -6256,14 +6256,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                p.println("      curEditorInfo: null");
            }
            p.println("      imeBindingState:");
                    u.mImeBindingState.dump("        ", p);
            u.mImeBindingState.dump(p, "        ");
            p.println("      enabledSession=" + u.mEnabledSession);
            p.println("      inFullscreenMode=" + u.mInFullscreenMode);
            p.println("      imeDrawsNavBar=" + u.mImeDrawsNavBar.get());
            p.println("      switchingController:");
            u.mSwitchingController.dump(p, "        ");
                    p.println("      mLastEnabledInputMethodsStr="
                            + u.mLastEnabledInputMethodsStr);
            p.println("      mLastEnabledInputMethodsStr=" + u.mLastEnabledInputMethodsStr);
        };
        synchronized (ImfLock.class) {
            mUserDataRepository.forAllUserData(userDataDump);
+2 −2

File changed.

Contains only whitespace changes.

+2 −2

File changed.

Contains only whitespace changes.