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

Commit 094ea03f authored by Adrian Roos's avatar Adrian Roos
Browse files

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
Merged-In: If1da19a3dd8c29542afc970b4b201d87547c27a9
parent b22a6d73
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2841,7 +2841,7 @@ public final class InputMethodManager {
    @UnsupportedAppUsage
    public int getInputMethodWindowVisibleHeight() {
        try {
            return mService.getInputMethodWindowVisibleHeight();
            return mService.getInputMethodWindowVisibleHeight(mClient);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ interface IInputMethodManager {
    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);

    void reportActivityView(in IInputMethodClient parentClient, int childDisplayId,
            in float[] matrixValues);
+52 −17
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.ContextThemeWrapper;
import android.view.DisplayInfo;
import android.view.IWindowManager;
@@ -303,6 +304,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    final InputMethodSettings mSettings;
    final SettingsObserver mSettingsObserver;
    final IWindowManager mIWindowManager;
    private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
            new SparseBooleanArray(0);
    final WindowManagerInternal mWindowManagerInternal;
    private final DisplayManagerInternal mDisplayManagerInternal;
    final HandlerCaller mCaller;
@@ -1219,6 +1222,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            clearPackageChangeState();
        }

        @Override
        public void onUidRemoved(int uid) {
            synchronized (mMethodMap) {
                mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
            }
        }

        private void clearPackageChangeState() {
            // No need to lock them because we access these fields only on getRegisteredHandler().
            mChangedPackages.clear();
@@ -2754,21 +2764,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            }
            final long ident = Binder.clearCallingIdentity();
            try {
                if (mCurClient == null || client == null
                        || mCurClient.client.asBinder() != client.asBinder()) {
                    // We need to check if this is the current client with
                    // focus in the window manager, to allow this call to
                    // be made before input is started in it.
                    final ClientState cs = mClients.get(client.asBinder());
                    if (cs == null) {
                        throw new IllegalArgumentException("unknown client " + client.asBinder());
                    }
                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
                            cs.selfReportedDisplayId)) {
                        Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
                if (!canInteractWithImeLocked(uid, client, "showSoftInput")) {
                    return false;
                }
                }
                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
                return showCurrentInputLocked(flags, resultReceiver);
            } finally {
@@ -3462,9 +3460,46 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()}
     */
    @Override
    public int getInputMethodWindowVisibleHeight() {
        // TODO(yukawa): Should we verify the display ID?
        return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
    @Deprecated
    public int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
        int callingUid = Binder.getCallingUid();
        return Binder.withCleanCallingIdentity(() -> {
            final int curTokenDisplayId;
            synchronized (mMethodMap) {
                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);
        });
    }

    private boolean canInteractWithImeLocked(int callingUid, IInputMethodClient client,
            String method) {
        if (mCurClient == null || client == null
                || mCurClient.client.asBinder() != client.asBinder()) {
            // We need to check if this is the current client with
            // focus in the window manager, to allow this call to
            // be made before input is started in it.
            final ClientState cs = mClients.get(client.asBinder());
            if (cs == null) {
                throw new IllegalArgumentException("unknown client " + client.asBinder());
            }
            if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
                    cs.selfReportedDisplayId)) {
                Slog.w(TAG, "Ignoring " + method + " of uid " + callingUid + ": " + client);
                return false;
            }
        }
        return true;
    }

    @Override
+1 −1
Original line number Diff line number Diff line
@@ -1694,7 +1694,7 @@ public final class MultiClientInputMethodManagerService {

        @BinderThread
        @Override
        public int getInputMethodWindowVisibleHeight() {
        public int getInputMethodWindowVisibleHeight(IInputMethodClient client) {
            reportNotSupported();
            return 0;
        }