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

Commit 5471c9a3 authored by Adrian Roos's avatar Adrian Roos Committed by Automerger Merge Worker
Browse files

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

parents 42c0065b b00cf71e
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