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
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index c093c22..e8ad327 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -476,7 +476,7 @@
 
     @AnyThread
     @NonNull
-    UserDataRepository.UserData getUserData(@UserIdInt int userId) {
+    UserData getUserData(@UserIdInt int userId) {
         return mUserDataRepository.getOrCreate(userId);
     }
 
@@ -1709,7 +1709,7 @@
         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 @@
      */
     // 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 @@
 
     @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 @@
     }
 
     @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 @@
     @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 @@
     }
 
     @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 @@
         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 @@
 
             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="
diff --git a/services/core/java/com/android/server/inputmethod/UserData.java b/services/core/java/com/android/server/inputmethod/UserData.java
new file mode 100644
index 0000000..ec5c9e6
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/UserData.java
@@ -0,0 +1,147 @@
+/*
+ * 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 + '}';
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
index 7c68d54..6f831cc 100644
--- a/services/core/java/com/android/server/inputmethod/UserDataRepository.java
+++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
@@ -18,18 +18,11 @@
 
 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 @@
             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 + '}';
-        }
-    }
 }
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
index 81fb1a0..d59f28b 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
@@ -98,8 +98,8 @@
         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;
     }