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

Commit b869c783 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Protect isInputMethodPickerShown() with TEST_INPUT_METHOD permission

IInputMethodManager#isInputMethodPickerShownForTest() was introduced
in Android P (API 28) to verify IME picker visibility in CTS [1].

To make it clear that that IPC method must be available only for
special testing purpose, this CL introduces an @hide permission

   android.permission.TEST_INPUT_METHOD

and requires it in

   InputMethodManagerService#isInputMethodPickerShownForTest().

This CL grants that permission to the shell process hence CTS tests
can still access to the corresponding test API by using
UiAutomation#adoptShellPermissionIdentity().

 [1]: I4e21625c32a0ca1abc740229efb3c7fcd97141cc
      eb570618

Bug: 237317525
Test: atest CtsInputMethodTestCases
Test: Manually verified as follows.
 1. adb logcat -b events | grep 237317525
 2. atest CtsInputMethodTestCases:InputMethodManagerTest#testIsInputMethodPickerShownProtection
Ignore-AOSP-First: For a security fix
Change-Id: Ie79a3e9d41ce22605ae083594d639c37d08b7def
parent d360900b
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -81,7 +81,11 @@ interface IInputMethodManager {
            int auxiliarySubtypeMode, int displayId);
            int auxiliarySubtypeMode, int displayId);


    void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
    void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
            + "android.Manifest.permission.TEST_INPUT_METHOD)")
    boolean isInputMethodPickerShownForTest();
    boolean isInputMethodPickerShownForTest();

    InputMethodSubtype getCurrentInputMethodSubtype();
    InputMethodSubtype getCurrentInputMethodSubtype();
    void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
    void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
    // This is kept due to @UnsupportedAppUsage.
    // This is kept due to @UnsupportedAppUsage.
+5 −0
Original line number Original line Diff line number Diff line
@@ -4068,6 +4068,11 @@
    <permission android:name="android.permission.BIND_INPUT_METHOD"
    <permission android:name="android.permission.BIND_INPUT_METHOD"
        android:protectionLevel="signature" />
        android:protectionLevel="signature" />


    <!-- Allows access to Test APIs defined in {@link android.view.inputmethod.InputMethodManager}.
         @hide -->
    <permission android:name="android.permission.TEST_INPUT_METHOD"
        android:protectionLevel="signature" />

    <!-- Must be required by an {@link android.media.midi.MidiDeviceService},
    <!-- Must be required by an {@link android.media.midi.MidiDeviceService},
         to ensure that only the system can bind to it.
         to ensure that only the system can bind to it.
         <p>Protection level: signature
         <p>Protection level: signature
+3 −0
Original line number Original line Diff line number Diff line
@@ -596,6 +596,9 @@
    <!-- Permission required for CTS test - ClipboardManagerTest -->
    <!-- Permission required for CTS test - ClipboardManagerTest -->
    <uses-permission android:name="android.permission.SET_CLIP_SOURCE" />
    <uses-permission android:name="android.permission.SET_CLIP_SOURCE" />


    <!-- Permission required for CTS test - CtsInputMethodTestCases -->
    <uses-permission android:name="android.permission.TEST_INPUT_METHOD" />

    <!-- Permission required for CTS test - FontManagerTest -->
    <!-- Permission required for CTS test - FontManagerTest -->
    <uses-permission android:name="android.permission.UPDATE_FONTS" />
    <uses-permission android:name="android.permission.UPDATE_FONTS" />


+15 −0
Original line number Original line Diff line number Diff line
@@ -294,6 +294,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
    final IWindowManager mIWindowManager;
    final IWindowManager mIWindowManager;
    private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
    private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
            new SparseBooleanArray(0);
            new SparseBooleanArray(0);
    private final SparseBooleanArray mLoggedDeniedIsInputMethodPickerShownForTestForUid =
            new SparseBooleanArray(0);
    final WindowManagerInternal mWindowManagerInternal;
    final WindowManagerInternal mWindowManagerInternal;
    final PackageManagerInternal mPackageManagerInternal;
    final PackageManagerInternal mPackageManagerInternal;
    final InputManagerInternal mInputManagerInternal;
    final InputManagerInternal mInputManagerInternal;
@@ -1465,6 +1467,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
        public void onUidRemoved(int uid) {
        public void onUidRemoved(int uid) {
            synchronized (ImfLock.class) {
            synchronized (ImfLock.class) {
                mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
                mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
                mLoggedDeniedIsInputMethodPickerShownForTestForUid.delete(uid);
            }
            }
        }
        }


@@ -4038,6 +4041,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
     * A test API for CTS to make sure that the input method menu is showing.
     * A test API for CTS to make sure that the input method menu is showing.
     */
     */
    public boolean isInputMethodPickerShownForTest() {
    public boolean isInputMethodPickerShownForTest() {
        if (mContext.checkCallingPermission(android.Manifest.permission.TEST_INPUT_METHOD)
                != PackageManager.PERMISSION_GRANTED) {
            final int callingUid = Binder.getCallingUid();
            synchronized (ImfLock.class) {
                if (!mLoggedDeniedIsInputMethodPickerShownForTestForUid.get(callingUid)) {
                    EventLog.writeEvent(0x534e4554, "237317525", callingUid, "");
                    mLoggedDeniedIsInputMethodPickerShownForTestForUid.put(callingUid, true);
                }
            }
            throw new SecurityException(
                    "isInputMethodPickerShownForTest requires TEST_INPUT_METHOD permission");
        }
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            return mMenuController.isisInputMethodPickerShownForTestLocked();
            return mMenuController.isisInputMethodPickerShownForTestLocked();
        }
        }