Move SettingsObserver#mLastEnabled to UserData

In order to make InputMethodManagerService.SettingsObserver multi-user
aware, one challenge is

  SettingsObserver#mLastEnabled,

which is tightly coupled with "single-user" concept. So this CL moves
it to UserData object in a mechanical manner.

There must be no behavior change in the single user mode anyway, and
for concurrent multi-user mode SettingsObserver is not yet fully
multi-user aware so this change is not yet used.

Bug: 342027196
Test: presubmit
Flag: android.view.inputmethod.concurrent_input_methods
Change-Id: Ie37a439fcd4155272efa9620ca20520ba4c58400
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3db9952..3bc8d53 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -572,8 +572,6 @@
     class SettingsObserver extends ContentObserver {
         int mUserId;
         boolean mRegistered = false;
-        @NonNull
-        String mLastEnabled = "";
 
         /**
          * <em>This constructor must be called within the lock.</em>
@@ -593,7 +591,6 @@
                 mRegistered = false;
             }
             if (mUserId != userId) {
-                mLastEnabled = "";
                 mUserId = userId;
             }
             resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -646,8 +643,9 @@
                     boolean enabledChanged = false;
                     String newEnabled = InputMethodSettingsRepository.get(mUserId)
                             .getEnabledInputMethodsStr();
-                    if (!mLastEnabled.equals(newEnabled)) {
-                        mLastEnabled = newEnabled;
+                    final var userData = getUserData(mUserId);
+                    if (!userData.mLastEnabledInputMethodsStr.equals(newEnabled)) {
+                        userData.mLastEnabledInputMethodsStr = newEnabled;
                         enabledChanged = true;
                     }
                     updateInputMethodsFromSettingsLocked(enabledChanged, mUserId);
@@ -657,8 +655,7 @@
 
         @Override
         public String toString() {
-            return "SettingsObserver{mUserId=" + mUserId + " mRegistered=" + mRegistered
-                    + " mLastEnabled=" + mLastEnabled + "}";
+            return "SettingsObserver{mUserId=" + mUserId + " mRegistered=" + mRegistered + "}";
         }
     }
 
@@ -1305,11 +1302,15 @@
 
         maybeInitImeNavbarConfigLocked(newUserId);
 
+        final var newUserData = getUserData(newUserId);
+
+        // TODO(b/342027196): Double check if we need to always reset upon user switching.
+        newUserData.mLastEnabledInputMethodsStr = "";
+
         // ContentObserver should be registered again when the user is changed
         mSettingsObserver.registerContentObserverLocked(newUserId);
 
         mCurrentUserId = newUserId;
-        final var newUserData = getUserData(newUserId);
         final String defaultImiId = SecureSettingsWrapper.getString(
                 Settings.Secure.DEFAULT_INPUT_METHOD, null, newUserId);
 
@@ -4263,9 +4264,8 @@
                 }
                 if (currentUser) {
                     // To avoid unnecessary "updateInputMethodsFromSettingsLocked" from happening.
-                    if (mSettingsObserver != null) {
-                        mSettingsObserver.mLastEnabled = settings.getEnabledInputMethodsStr();
-                    }
+                    final var userData = getUserData(userId);
+                    userData.mLastEnabledInputMethodsStr = settings.getEnabledInputMethodsStr();
                     updateInputMethodsFromSettingsLocked(false /* enabledChanged */, userId);
                 }
             }
@@ -6104,6 +6104,8 @@
                         p.println("      inFullscreenMode=" + u.mInFullscreenMode);
                         p.println("      switchingController:");
                         u.mSwitchingController.dump(p, "        ");
+                        p.println("      mLastEnabledInputMethodsStr="
+                                + u.mLastEnabledInputMethodsStr);
                     };
             mUserDataRepository.forAllUserData(userDataDump);
 
diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
index 48284fb..59411ad 100644
--- a/services/core/java/com/android/server/inputmethod/UserDataRepository.java
+++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
@@ -174,6 +174,13 @@
                 mEnabledAccessibilitySessions = new SparseArray<>();
 
         /**
+         * A per-user cache of {@link InputMethodSettings#getEnabledInputMethodsStr()}.
+         */
+        @GuardedBy("ImfLock.class")
+        @NonNull
+        String mLastEnabledInputMethodsStr = "";
+
+        /**
          * Intended to be instantiated only from this file.
          */
         private UserData(@UserIdInt int userId,