Restrict getInputMethodWindowVisibleHeight

Make sure only the app currently interacting with the IME can
query this, and restrict the API to apps targeting SDKs before T

Fixes: 204906124
Test: atest 'InputMethodManagerTest#getInputMethodWindowVisibleHeight_returnsZeroIfNotFocused'
Change-Id: If1da19a3dd8c29542afc970b4b201d87547c27a9
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 2359d8d..34107a2 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -3220,10 +3220,11 @@
      * @return Something that is not well-defined.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(trackingBug = 204906124, maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
+            publicAlternatives = "Use {@link android.view.WindowInsets} instead")
     public int getInputMethodWindowVisibleHeight() {
         try {
-            return mService.getInputMethodWindowVisibleHeight();
+            return mService.getInputMethodWindowVisibleHeight(mClient);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 0df3e87..c5346b9 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -67,7 +67,7 @@
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
     // This is kept due to @UnsupportedAppUsage.
     // TODO(Bug 113914148): Consider removing this.
-    int getInputMethodWindowVisibleHeight();
+    int getInputMethodWindowVisibleHeight(in IInputMethodClient client);
 
     oneway void reportPerceptibleAsync(in IBinder windowToken, boolean perceptible);
     /** Remove the IME surface. Requires INTERNAL_SYSTEM_WINDOW permission. */
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0b7e391..e9c3348 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -122,6 +122,7 @@
 import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.proto.ProtoOutputStream;
 import android.view.IWindowManager;
 import android.view.InputChannel;
@@ -276,6 +277,8 @@
     final InputMethodSettings mSettings;
     final SettingsObserver mSettingsObserver;
     final IWindowManager mIWindowManager;
+    private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
+            new SparseBooleanArray(0);
     final WindowManagerInternal mWindowManagerInternal;
     final PackageManagerInternal mPackageManagerInternal;
     final InputManagerInternal mInputManagerInternal;
@@ -1381,6 +1384,13 @@
             clearPackageChangeState();
         }
 
+        @Override
+        public void onUidRemoved(int uid) {
+            synchronized (ImfLock.class) {
+                mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
+            }
+        }
+
         private void clearPackageChangeState() {
             // No need to lock them because we access these fields only on getRegisteredHandler().
             mChangedPackages.clear();
@@ -4145,13 +4155,26 @@
      * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight(int)}
      */
     @Override
-    public int getInputMethodWindowVisibleHeight() {
-        // TODO(yukawa): Should we verify the display ID?
-        final int curTokenDisplayId;
-        synchronized (ImfLock.class) {
-            curTokenDisplayId = mCurTokenDisplayId;
-        }
-        return mWindowManagerInternal.getInputMethodWindowVisibleHeight(curTokenDisplayId);
+    @Deprecated
+    public int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
+        int callingUid = Binder.getCallingUid();
+        return Binder.withCleanCallingIdentity(() -> {
+            final int curTokenDisplayId;
+            synchronized (ImfLock.class) {
+                if (!canInteractWithImeLocked(callingUid, client,
+                        "getInputMethodWindowVisibleHeight")) {
+                    if (!mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.get(callingUid)) {
+                        EventLog.writeEvent(0x534e4554, "204906124", callingUid, "");
+                        mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.put(callingUid, true);
+                    }
+                    return 0;
+                }
+                // This should probably use the caller's display id, but because this is unsupported
+                // and maintained only for compatibility, there's no point in fixing it.
+                curTokenDisplayId = mCurTokenDisplayId;
+            }
+            return mWindowManagerInternal.getInputMethodWindowVisibleHeight(curTokenDisplayId);
+        });
     }
 
     @Override