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

Commit 8c14f908 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Extract out UserDataRepository.UserData

As a preparation to reduce redundant usages of IMMS#getUserData(),
this CL extracts out UserDataRepository.UserData so that we can refer
to UserData a bit more easily.

This is a mechanical code refactoring. There must be no behavior
change.

Bug: 353307830
Test: presubmit
Flag: EXEMPT refactor
Change-Id: Ib2dcb59c9de8ea1fd428dd2fe3ee87d954cc294a
parent 0adfd5f3
Loading
Loading
Loading
Loading
+9 −12
Original line number Diff line number Diff line
@@ -476,7 +476,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.

    @AnyThread
    @NonNull
    UserDataRepository.UserData getUserData(@UserIdInt int userId) {
    UserData getUserData(@UserIdInt int userId) {
        return mUserDataRepository.getOrCreate(userId);
    }

@@ -1709,7 +1709,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        clearClientSessionLocked(client);
        clearClientSessionForAccessibilityLocked(client);
        // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
        @SuppressWarnings("GuardedBy") Consumer<UserDataRepository.UserData> clientRemovedForUser =
        @SuppressWarnings("GuardedBy") Consumer<UserData> clientRemovedForUser =
                userData -> onClientRemovedInternalLocked(client, userData);
        mUserDataRepository.forAllUserData(clientRemovedForUser);
    }
@@ -1719,8 +1719,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
     */
    // TODO(b/325515685): Move this method to InputMethodBindingController
    @GuardedBy("ImfLock.class")
    private void onClientRemovedInternalLocked(ClientState client,
            @NonNull UserDataRepository.UserData userData) {
    private void onClientRemovedInternalLocked(ClientState client, @NonNull UserData userData) {
        final int userId = userData.mUserId;
        if (userData.mCurClient == client) {
            hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
@@ -2576,8 +2575,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.

    @GuardedBy("ImfLock.class")
    @InputMethodNavButtonFlags
    private int getInputMethodNavButtonFlagsLocked(
            @NonNull UserDataRepository.UserData userData) {
    private int getInputMethodNavButtonFlagsLocked(@NonNull UserData userData) {
        final int userId = userData.mUserId;
        final var bindingController = userData.mBindingController;
        // Whether the current display has a navigation bar. When this is false (e.g. emulator),
@@ -4804,8 +4802,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    }

    @GuardedBy("ImfLock.class")
    void setEnabledSessionLocked(SessionState session,
            @NonNull UserDataRepository.UserData userData) {
    void setEnabledSessionLocked(SessionState session, @NonNull UserData userData) {
        if (userData.mEnabledSession != session) {
            if (userData.mEnabledSession != null && userData.mEnabledSession.mSession != null) {
                if (DEBUG) Slog.v(TAG, "Disabling: " + userData.mEnabledSession);
@@ -4824,7 +4821,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    @GuardedBy("ImfLock.class")
    void setEnabledSessionForAccessibilityLocked(
            SparseArray<AccessibilitySessionState> accessibilitySessions,
            @NonNull UserDataRepository.UserData userData) {
            @NonNull UserData userData) {
        // mEnabledAccessibilitySessions could the same object as accessibilitySessions.
        SparseArray<IAccessibilityInputMethodSession> disabledSessions = new SparseArray<>();
        for (int i = 0; i < userData.mEnabledAccessibilitySessions.size(); i++) {
@@ -5329,7 +5326,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    }

    @GuardedBy("ImfLock.class")
    void sendOnNavButtonFlagsChangedLocked(@NonNull UserDataRepository.UserData userData) {
    void sendOnNavButtonFlagsChangedLocked(@NonNull UserData userData) {
        final var bindingController = userData.mBindingController;
        final IInputMethodInvoker curMethod = bindingController.getCurMethod();
        if (curMethod == null) {
@@ -5345,7 +5342,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        final boolean value =
                InputMethodDrawsNavBarResourceMonitor.evaluate(mContext, profileParentId);
        final var profileUserIds = mUserManagerInternal.getProfileIds(profileParentId, false);
        final ArrayList<UserDataRepository.UserData> updatedUsers = new ArrayList<>();
        final ArrayList<UserData> updatedUsers = new ArrayList<>();
        for (int profileUserId : profileUserIds) {
            final var userData = getUserData(profileUserId);
            userData.mImeDrawsNavBar.set(value);
@@ -6125,7 +6122,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.

            p.println("  mUserDataRepository=");
            // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
            @SuppressWarnings("GuardedBy") Consumer<UserDataRepository.UserData> userDataDump =
            @SuppressWarnings("GuardedBy") Consumer<UserData> userDataDump =
                    u -> {
                        p.println("    mUserId=" + u.mUserId);
                        p.println("      hasMainConnection="
+147 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.inputmethod;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.util.SparseArray;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.window.ImeOnBackInvokedDispatcher;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.inputmethod.IRemoteInputConnection;

import java.util.concurrent.atomic.AtomicBoolean;

/** Placeholder for all IMMS user specific fields */
final class UserData {
    @UserIdInt
    final int mUserId;

    @NonNull
    final InputMethodBindingController mBindingController;

    @NonNull
    final InputMethodSubtypeSwitchingController mSwitchingController =
            new InputMethodSubtypeSwitchingController();

    @NonNull
    final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController =
            new HardwareKeyboardShortcutController();

    /**
     * Have we called mCurMethod.bindInput()?
     */
    @GuardedBy("ImfLock.class")
    boolean mBoundToMethod = false;

    /**
     * Have we called bindInput() for accessibility services?
     */
    @GuardedBy("ImfLock.class")
    boolean mBoundToAccessibility;

    @GuardedBy("ImfLock.class")
    @NonNull
    ImeBindingState mImeBindingState = ImeBindingState.newEmptyState();

    @GuardedBy("ImfLock.class")
    @Nullable
    ClientState mCurClient = null;

    @GuardedBy("ImfLock.class")
    boolean mInFullscreenMode;

    /**
     * The {@link IRemoteInputConnection} last provided by the current client.
     */
    @GuardedBy("ImfLock.class")
    @Nullable
    IRemoteInputConnection mCurInputConnection;

    /**
     * The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
     * receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
     */
    @GuardedBy("ImfLock.class")
    @Nullable
    ImeOnBackInvokedDispatcher mCurImeDispatcher;

    /**
     * The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
     */
    @GuardedBy("ImfLock.class")
    @Nullable
    IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;

    /**
     * The {@link EditorInfo} last provided by the current client.
     */
    @GuardedBy("ImfLock.class")
    @Nullable
    EditorInfo mCurEditorInfo;

    /**
     * The token tracking the current IME show request that is waiting for a connection to an
     * IME, otherwise {@code null}.
     */
    @GuardedBy("ImfLock.class")
    @Nullable
    ImeTracker.Token mCurStatsToken;

    /**
     * Currently enabled session.
     */
    @GuardedBy("ImfLock.class")
    @Nullable
    InputMethodManagerService.SessionState mEnabledSession;

    @GuardedBy("ImfLock.class")
    @Nullable
    SparseArray<InputMethodManagerService.AccessibilitySessionState>
            mEnabledAccessibilitySessions = new SparseArray<>();

    /**
     * A per-user cache of {@link InputMethodSettings#getEnabledInputMethodsStr()}.
     */
    @GuardedBy("ImfLock.class")
    @NonNull
    String mLastEnabledInputMethodsStr = "";

    /**
     * {@code true} when the IME is responsible for drawing the navigation bar and its buttons.
     */
    @NonNull
    final AtomicBoolean mImeDrawsNavBar = new AtomicBoolean();

    /**
     * Intended to be instantiated only from this file.
     */
    UserData(@UserIdInt int userId,
            @NonNull InputMethodBindingController bindingController) {
        mUserId = userId;
        mBindingController = bindingController;
    }

    @Override
    public String toString() {
        return "UserData{" + "mUserId=" + mUserId + '}';
    }
}
+0 −123
Original line number Diff line number Diff line
@@ -18,18 +18,11 @@ package com.android.server.inputmethod;

import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.util.SparseArray;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.window.ImeOnBackInvokedDispatcher;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.inputmethod.IRemoteInputConnection;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
import java.util.function.IntFunction;
@@ -87,120 +80,4 @@ final class UserDataRepository {
            mUserDataLock.writeLock().unlock();
        }
    }

    /** Placeholder for all IMMS user specific fields */
    static final class UserData {
        @UserIdInt
        final int mUserId;

        @NonNull
        final InputMethodBindingController mBindingController;

        @NonNull
        final InputMethodSubtypeSwitchingController mSwitchingController;

        @NonNull
        final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController;

        /**
         * Have we called mCurMethod.bindInput()?
         */
        @GuardedBy("ImfLock.class")
        boolean mBoundToMethod = false;

        /**
         * Have we called bindInput() for accessibility services?
         */
        @GuardedBy("ImfLock.class")
        boolean mBoundToAccessibility;

        @GuardedBy("ImfLock.class")
        @NonNull
        ImeBindingState mImeBindingState = ImeBindingState.newEmptyState();

        @GuardedBy("ImfLock.class")
        @Nullable
        ClientState mCurClient = null;

        @GuardedBy("ImfLock.class")
        boolean mInFullscreenMode;

        /**
         * The {@link IRemoteInputConnection} last provided by the current client.
         */
        @GuardedBy("ImfLock.class")
        @Nullable
        IRemoteInputConnection mCurInputConnection;

        /**
         * The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
         * receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
         */
        @GuardedBy("ImfLock.class")
        @Nullable
        ImeOnBackInvokedDispatcher mCurImeDispatcher;

        /**
         * The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
         */
        @GuardedBy("ImfLock.class")
        @Nullable
        IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;

        /**
         * The {@link EditorInfo} last provided by the current client.
         */
        @GuardedBy("ImfLock.class")
        @Nullable
        EditorInfo mCurEditorInfo;

        /**
         * The token tracking the current IME show request that is waiting for a connection to an
         * IME, otherwise {@code null}.
         */
        @GuardedBy("ImfLock.class")
        @Nullable
        ImeTracker.Token mCurStatsToken;

        /**
         * Currently enabled session.
         */
        @GuardedBy("ImfLock.class")
        @Nullable
        InputMethodManagerService.SessionState mEnabledSession;

        @GuardedBy("ImfLock.class")
        @Nullable
        SparseArray<InputMethodManagerService.AccessibilitySessionState>
                mEnabledAccessibilitySessions = new SparseArray<>();

        /**
         * A per-user cache of {@link InputMethodSettings#getEnabledInputMethodsStr()}.
         */
        @GuardedBy("ImfLock.class")
        @NonNull
        String mLastEnabledInputMethodsStr = "";

        /**
         * {@code true} when the IME is responsible for drawing the navigation bar and its buttons.
         */
        @NonNull
        final AtomicBoolean mImeDrawsNavBar = new AtomicBoolean();

        /**
         * Intended to be instantiated only from this file.
         */
        private UserData(@UserIdInt int userId,
                @NonNull InputMethodBindingController bindingController) {
            mUserId = userId;
            mBindingController = bindingController;
            mSwitchingController = new InputMethodSubtypeSwitchingController();
            mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController();
        }

        @Override
        public String toString() {
            return "UserData{" + "mUserId=" + mUserId + '}';
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -98,8 +98,8 @@ public final class UserDataRepositoryTest {
        assertThat(allUserData.get(0).mBindingController.getUserId()).isEqualTo(ANY_USER_ID);
    }

    private List<UserDataRepository.UserData> collectUserData(UserDataRepository repository) {
        final var collected = new ArrayList<UserDataRepository.UserData>();
    private List<UserData> collectUserData(UserDataRepository repository) {
        final var collected = new ArrayList<UserData>();
        repository.forAllUserData(userData -> collected.add(userData));
        return collected;
    }