Fix some issues in FrameworkInputMethodSystemServerTests

- Fix wrong src path in InputMethodSystemServerTests/Android.bp by CL[1]
- In IMMS, Make ImeTrackerService by CL[2] can inject a test looper, in
  case InputMethodManagerServiceTestBase#setUp got exception by null
  looper queue.
- Remove unused test method IMMS#getVisibilityStateComputer().
- Add ImfLock block in IMMS#getVisibilityApplier for fixing linter
  check.
- Fix a potential NPE when calling mImeTrackerService.onImmsUpdate that
  the statsToken may null during testing.
- Remove duplicate calls in testApplyImeVisibility_throwForInvalidState.
- Add missed showFlag parameters in testPerformShowIme.
- Fix verifyShowSoftInput logic when no need to verify showFlags cases
- Add a regression unit test In ImeVisibilityStateComputerTest for
  Bug 265439883:
  testComputeState_lastImeRequestedVisible_preserved_When_StateUnChanged

 [1]: I84f1a1b25eef4a757d8da27807285e08417458b4
 [2]: I432bab2de58a9df2c421bb00946ab211de445660

Bug: 246309664
Bug: 240359838
Test: atest FrameworkInputMethodSystemServerTests all passed
Change-Id: I0890641868f9200c613af0d6ee7014e4c7b1e7ed
diff --git a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
index 60167b4..da65f27 100644
--- a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
+++ b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
@@ -59,13 +59,16 @@
     private static final long TIMEOUT_MS = 10_000;
 
     /** Handler for registering timeouts for live entries. */
-    private final Handler mHandler =
-            new Handler(Looper.myLooper(), null /* callback */, true /* async */);
+    private final Handler mHandler;
 
     /** Singleton instance of the History. */
     @GuardedBy("ImeTrackerService.this")
     private final History mHistory = new History();
 
+    ImeTrackerService(@NonNull Looper looper) {
+        mHandler = new Handler(looper, null /* callback */, true /* async */);
+    }
+
     @NonNull
     @Override
     public synchronized IBinder onRequestShow(int uid, @ImeTracker.Origin int origin,
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 19108a8..9899719 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -89,6 +89,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.LocaleList;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Process;
@@ -1105,7 +1106,7 @@
             new SoftInputShowHideHistory();
 
     @NonNull
-    private final ImeTrackerService mImeTrackerService = new ImeTrackerService();
+    private final ImeTrackerService mImeTrackerService;
 
     class SettingsObserver extends ContentObserver {
         int mUserId;
@@ -1662,6 +1663,8 @@
                                 true /* allowIo */);
         thread.start();
         mHandler = Handler.createAsync(thread.getLooper(), this);
+        mImeTrackerService = new ImeTrackerService(serviceThreadForTesting != null
+                ? serviceThreadForTesting.getLooper() : Looper.getMainLooper());
         // Note: SettingsObserver doesn't register observers in its constructor.
         mSettingsObserver = new SettingsObserver(mHandler);
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
@@ -4612,7 +4615,9 @@
                 info.requestWindowName, info.imeControlTargetName, info.imeLayerTargetName,
                 info.imeSurfaceParentName));
 
-        mImeTrackerService.onImmsUpdate(statsToken.mBinder, info.requestWindowName);
+        if (statsToken != null) {
+            mImeTrackerService.onImmsUpdate(statsToken.mBinder, info.requestWindowName);
+        }
     }
 
     @BinderThread
@@ -4654,13 +4659,10 @@
     }
 
     @VisibleForTesting
-    ImeVisibilityStateComputer getVisibilityStateComputer() {
-        return mVisibilityStateComputer;
-    }
-
-    @VisibleForTesting
     ImeVisibilityApplier getVisibilityApplier() {
-        return mVisibilityApplier;
+        synchronized (ImfLock.class) {
+            return mVisibilityApplier;
+        }
     }
 
     @GuardedBy("ImfLock.class")
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 70a5c3f..05a8b11 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -28,7 +28,7 @@
     ],
 
     srcs: [
-        "src/server/**/*.java",
+        "src/com/android/server/inputmethod/**/*.java",
     ],
 
     static_libs: [
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index 73d04c6..720f486 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -65,19 +65,24 @@
 
     @Test
     public void testPerformShowIme() throws Exception {
-        mVisibilityApplier.performShowIme(mWindowToken, null, null, SHOW_SOFT_INPUT);
+        synchronized (ImfLock.class) {
+            mVisibilityApplier.performShowIme(mWindowToken, null /* statsToken */,
+                    InputMethodManager.SHOW_IMPLICIT, null, SHOW_SOFT_INPUT);
+        }
         verifyShowSoftInput(false, true, InputMethodManager.SHOW_IMPLICIT);
     }
 
     @Test
     public void testPerformHideIme() throws Exception {
-        mVisibilityApplier.performHideIme(mWindowToken, null, null, HIDE_SOFT_INPUT);
+        synchronized (ImfLock.class) {
+            mVisibilityApplier.performHideIme(mWindowToken, null /* statsToken */, null,
+                    HIDE_SOFT_INPUT);
+        }
         verifyHideSoftInput(false, true);
     }
 
     @Test
     public void testApplyImeVisibility_throwForInvalidState() {
-        mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_INVALID);
         assertThrows(IllegalArgumentException.class,
                 () -> mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_INVALID));
     }
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
index 8415fe1..a1b9b98 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
@@ -30,6 +30,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.inputmethod.InputMethodManager;
@@ -177,9 +178,28 @@
         assertThat(state.getImeDisplayId()).isEqualTo(FALLBACK_DISPLAY_ID);
     }
 
-    private void initImeTargetWindowState(IBinder windowToken) {
+    @Test
+    public void testComputeState_lastImeRequestedVisible_preserved_When_StateUnChanged() {
+        // Assume the last IME targeted window has requested IME visible
+        final IBinder lastImeTargetWindowToken = new Binder();
+        mInputMethodManagerService.mLastImeTargetWindow = lastImeTargetWindowToken;
+        mComputer.requestImeVisibility(lastImeTargetWindowToken, true);
+        final ImeTargetWindowState lastState = mComputer.getWindowStateOrNull(
+                lastImeTargetWindowToken);
+        assertThat(lastState.isRequestedImeVisible()).isTrue();
+
+        // Verify when focusing the next window with STATE_UNCHANGED flag, the last IME
+        // visibility state will be preserved to the current window state.
+        final ImeTargetWindowState stateWithUnChangedFlag = initImeTargetWindowState(mWindowToken);
+        mComputer.computeState(stateWithUnChangedFlag, true /* allowVisible */);
+        assertThat(stateWithUnChangedFlag.isRequestedImeVisible()).isEqualTo(
+                lastState.isRequestedImeVisible());
+    }
+
+    private ImeTargetWindowState initImeTargetWindowState(IBinder windowToken) {
         final ImeTargetWindowState state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNCHANGED,
                 0, true, true, true);
         mComputer.setWindowState(windowToken, state);
+        return state;
     }
 }
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 804bb49..dbdffd0 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -71,6 +71,8 @@
 
 /** Base class for testing {@link InputMethodManagerService}. */
 public class InputMethodManagerServiceTestBase {
+    private static final int NO_VERIFY_SHOW_FLAGS = -1;
+
     protected static final String TEST_SELECTED_IME_ID = "test.ime";
     protected static final String TEST_EDITOR_PKG_NAME = "test.editor";
     protected static final String TEST_FOCUSED_WINDOW_NAME = "test.editor/activity";
@@ -239,7 +241,7 @@
 
     protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput)
             throws RemoteException {
-        verifyShowSoftInput(setVisible, showSoftInput, anyInt());
+        verifyShowSoftInput(setVisible, showSoftInput, NO_VERIFY_SHOW_FLAGS);
     }
 
     protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput, int showFlags)
@@ -249,7 +251,8 @@
                     .setCurrentMethodVisible();
         }
         verify(mMockInputMethod, times(showSoftInput ? 1 : 0))
-                .showSoftInput(any(), any(), eq(showFlags), any());
+                .showSoftInput(any(), any(),
+                        showFlags != NO_VERIFY_SHOW_FLAGS ? eq(showFlags) : anyInt(), any());
     }
 
     protected void verifyHideSoftInput(boolean setNotVisible, boolean hideSoftInput)