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

Commit b00cf71e authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Switch IME subtypes with keyboard shortcuts" into udc-dev

parents af730e95 00a86c83
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -177,6 +177,14 @@ public abstract class InputMethodManagerInternal {
     */
    public abstract void unbindAccessibilityFromCurrentClient(int accessibilityConnectionId);

    /**
     * Switch the keyboard layout in response to a keyboard shortcut.
     *
     * @param direction {@code 1} to switch to the next subtype, {@code -1} to switch to the
     *                           previous subtype.
     */
    public abstract void switchKeyboardLayout(int direction);

    /**
     * Fake implementation of {@link InputMethodManagerInternal}.  All the methods do nothing.
     */
@@ -256,6 +264,10 @@ public abstract class InputMethodManagerInternal {
                @Override
                public void maybeFinishStylusHandwriting() {
                }

                @Override
                public void switchKeyboardLayout(int direction) {
                }
            };

    /**
+24 −8
Original line number Diff line number Diff line
@@ -4050,6 +4050,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
            if (!calledWithValidTokenLocked(token)) {
                return false;
            }
            return switchToNextInputMethodLocked(token, onlyCurrentIme);
        }
    }

    @GuardedBy("ImfLock.class")
    private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme) {
        final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
                onlyCurrentIme, mMethodMap.get(getSelectedMethodIdLocked()), mCurrentSubtype);
        if (nextSubtype == null) {
@@ -4059,7 +4065,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
                nextSubtype.mSubtypeId);
        return true;
    }
    }

    @BinderThread
    private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token) {
@@ -5749,6 +5754,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
            mHandler.removeMessages(MSG_FINISH_HANDWRITING);
            mHandler.obtainMessage(MSG_FINISH_HANDWRITING).sendToTarget();
        }

        @Override
        public void switchKeyboardLayout(int direction) {
            synchronized (ImfLock.class) {
                if (direction > 0) {
                    switchToNextInputMethodLocked(null /* token */, true /* onlyCurrentIme */);
                } else {
                    // TODO(b/258853866): Support backwards switching.
                }
            }
        }
    }

    @BinderThread
+22 −10
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
@@ -160,6 +161,7 @@ import android.service.dreams.IDreamManager;
import android.service.vr.IPersistentVrStateCallbacks;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.MathUtils;
import android.util.MutableBoolean;
@@ -398,7 +400,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    ActivityTaskManagerInternal mActivityTaskManagerInternal;
    AutofillManagerInternal mAutofillManagerInternal;
    InputManagerInternal mInputManagerInternal;
    InputMethodManagerInternal mInputMethodManagerInternal;
    DreamManagerInternal mDreamManagerInternal;
    PowerManagerInternal mPowerManagerInternal;
    IStatusBarService mStatusBarService;
@@ -659,6 +660,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    private static final int MSG_HANDLE_ALL_APPS = 22;
    private static final int MSG_LAUNCH_ASSIST = 23;
    private static final int MSG_RINGER_TOGGLE_CHORD = 24;
    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;

    private class PolicyHandler extends Handler {
        @Override
@@ -729,6 +731,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                case MSG_SCREENSHOT_CHORD:
                    handleScreenShot(msg.arg1);
                    break;
                case MSG_SWITCH_KEYBOARD_LAYOUT:
                    handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
                    break;
            }
        }
    }
@@ -1025,14 +1030,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    break;
                case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
                    if (mDismissImeOnBackKeyPressed) {
                        if (mInputMethodManagerInternal == null) {
                            mInputMethodManagerInternal =
                                    LocalServices.getService(InputMethodManagerInternal.class);
                        }
                        if (mInputMethodManagerInternal != null) {
                            mInputMethodManagerInternal.hideCurrentInputMethod(
                        InputMethodManagerInternal.get().hideCurrentInputMethod(
                                    SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME);
                        }
                    } else {
                        shortPressPowerGoHome();
                    }
@@ -3170,7 +3169,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                }
                if (down && repeatCount == 0) {
                    int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                    mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
                    sendSwitchKeyboardLayout(event, direction);
                    return key_consumed;
                }
                break;
@@ -3420,7 +3419,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    if (KeyEvent.metaStateHasModifiers(metaState & ~KeyEvent.META_SHIFT_MASK,
                            KeyEvent.META_CTRL_ON)) {
                        int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                        mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
                        sendSwitchKeyboardLayout(event, direction);
                        return true;
                    }
                }
@@ -3446,6 +3445,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return false;
    }

    private void sendSwitchKeyboardLayout(@NonNull KeyEvent event, int direction) {
        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, event.getDeviceId(),
                direction).sendToTarget();
    }

    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
            InputMethodManagerInternal.get().switchKeyboardLayout(direction);
        } else {
            mWindowManagerFuncs.switchKeyboardLayout(deviceId, direction);
        }
    }

    private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
            int policyFlags) {
        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
+3 −1
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ public class InputMethodManagerServiceTestBase {
                mockitoSession()
                        .initMocks(this)
                        .strictness(Strictness.LENIENT)
                        .mockStatic(LocalServices.class)
                        .spyStatic(LocalServices.class)
                        .mockStatic(ServiceManager.class)
                        .mockStatic(SystemServerInitThreadPool.class)
                        .startMocking();
@@ -212,6 +212,7 @@ public class InputMethodManagerServiceTestBase {
                new InputMethodManagerService.Lifecycle(mContext, mInputMethodManagerService);

        // Public local InputMethodManagerService.
        LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
        lifecycle.onStart();
        try {
            // After this boot phase, services can broadcast Intents.
@@ -237,6 +238,7 @@ public class InputMethodManagerServiceTestBase {
        if (mMockingSession != null) {
            mMockingSession.finishMocking();
        }
        LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
    }

    protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput)
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.inputmethod;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;

import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.dx.mockito.inline.extended.ExtendedMockito;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class SwitchKeyboardLayoutTest extends InputMethodManagerServiceTestBase {
    @Test
    public void testSwitchToNextKeyboardLayout() {
        ExtendedMockito.spyOn(mInputMethodManagerService.mSwitchingController);
        InputMethodManagerInternal.get().switchKeyboardLayout(1);
        verify(mInputMethodManagerService.mSwitchingController)
                .getNextInputMethodLocked(eq(true) /* onlyCurrentIme */, any(), any());
    }
}
Loading