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

Commit 2d9accb2 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Revert "Switch and store keyboard layouts based on IME subtype."

This reverts commit d5f7ed9f [1].

Reason for revert:
This is the part 2 of a series of reverts to unlaunch Bug 25752812,
which aimed to improve UX but did not work well.

See I7a2ed6dd39dcd8207d3d94e12cd01d5d67ba4bb5 for the detailed reason
of revert.

 [1]: Ie88ce1ab77dbfe03ab51d89c1dc9e0a7ddbb3216

Bug: 66498367
Test: Manually done
Change-Id: I207919e3cb081d77712371f58463a5d423717c8f
parent 36abd8a6
Loading
Loading
Loading
Loading
+0 −7
Original line number Original line Diff line number Diff line
@@ -26,8 +26,6 @@ import android.os.IBinder;
import android.view.InputDevice;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEvent;
import android.view.PointerIcon;
import android.view.PointerIcon;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;


/** @hide */
/** @hide */
interface IInputManager {
interface IInputManager {
@@ -67,11 +65,6 @@ interface IInputManager {
            String keyboardLayoutDescriptor);
            String keyboardLayoutDescriptor);
    void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
    void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            String keyboardLayoutDescriptor);
            String keyboardLayoutDescriptor);
    KeyboardLayout getKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype);
    void setKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype,
            String keyboardLayoutDescriptor);


    // Registers an input devices changed listener.
    // Registers an input devices changed listener.
    void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
    void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
+0 −46
Original line number Original line Diff line number Diff line
@@ -42,8 +42,6 @@ import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.PointerIcon;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;


import com.android.internal.os.SomeArgs;
import com.android.internal.os.SomeArgs;


@@ -702,50 +700,6 @@ public final class InputManager {
        }
        }
    }
    }



    /**
     * Gets the keyboard layout for the specified input device and IME subtype.
     *
     * @param identifier The identifier for the input device.
     * @param inputMethodInfo The input method.
     * @param inputMethodSubtype The input method subtype.
     *
     * @return The associated {@link KeyboardLayout}, or null if one has not been set.
     *
     * @hide
     */
    public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype) {
        try {
            return mIm.getKeyboardLayoutForInputDevice(
                    identifier, inputMethodInfo, inputMethodSubtype);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    /**
     * Sets the keyboard layout for the specified input device and IME subtype pair.
     *
     * @param identifier The identifier for the input device.
     * @param inputMethodInfo The input method with which to associate the keyboard layout.
     * @param inputMethodSubtype The input method subtype which which to associate the keyboard
     *                           layout.
     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to set
     *
     * @hide
     */
    public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype,
            String keyboardLayoutDescriptor) {
        try {
            mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
                    inputMethodSubtype, keyboardLayoutDescriptor);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    /**
    /**
     * Gets the TouchCalibration applied to the specified input device's coordinates.
     * Gets the TouchCalibration applied to the specified input device's coordinates.
     *
     *
+0 −6
Original line number Original line Diff line number Diff line
@@ -123,10 +123,4 @@ public class TouchCalibration implements Parcelable {
               Float.floatToIntBits(mYScale)  ^
               Float.floatToIntBits(mYScale)  ^
               Float.floatToIntBits(mYOffset);
               Float.floatToIntBits(mYOffset);
    }
    }

    @Override
    public String toString() {
        return String.format("[%f, %f, %f, %f, %f, %f]",
                mXScale, mXYMix, mXOffset, mYXMix, mYScale, mYOffset);
    }
}
}
+0 −71
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2016 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.internal.inputmethod;

import android.text.TextUtils;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;

import java.util.Objects;

public class InputMethodSubtypeHandle {
    private final String mInputMethodId;
    private final int mSubtypeId;

    public InputMethodSubtypeHandle(InputMethodInfo info, InputMethodSubtype subtype) {
        mInputMethodId = info.getId();
        if (subtype != null) {
            mSubtypeId = subtype.hashCode();
        } else {
            mSubtypeId = 0;
        }
    }

    public InputMethodSubtypeHandle(String inputMethodId, int subtypeId) {
        mInputMethodId = inputMethodId;
        mSubtypeId = subtypeId;
    }

    public String getInputMethodId() {
        return mInputMethodId;
    }

    public int getSubtypeId() {
        return mSubtypeId;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || !(o instanceof InputMethodSubtypeHandle)) {
            return false;
        }
        InputMethodSubtypeHandle other = (InputMethodSubtypeHandle) o;
        return TextUtils.equals(mInputMethodId, other.getInputMethodId())
                && mSubtypeId == other.getSubtypeId();
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(mInputMethodId) * 31 + mSubtypeId;
    }

    @Override
    public String toString() {
        return "InputMethodSubtypeHandle{mInputMethodId=" + mInputMethodId
            + ", mSubtypeId=" + mSubtypeId + "}";
    }
}
+41 −179
Original line number Original line Diff line number Diff line
@@ -22,7 +22,6 @@ import android.os.LocaleList;
import android.os.ShellCallback;
import android.os.ShellCallback;
import android.util.Log;
import android.util.Log;
import android.view.Display;
import android.view.Display;
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.SomeArgs;
@@ -79,8 +78,6 @@ import android.os.Message;
import android.os.MessageQueue;
import android.os.MessageQueue;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Settings.SettingNotFoundException;
@@ -101,6 +98,7 @@ import android.view.Surface;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.Toast;


import java.io.File;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileDescriptor;
@@ -174,7 +172,8 @@ public class InputManagerService extends IInputManager.Stub
    private final ArrayList<InputDevice>
    private final ArrayList<InputDevice>
            mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
            mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
    private boolean mKeyboardLayoutNotificationShown;
    private boolean mKeyboardLayoutNotificationShown;
    private InputMethodSubtypeHandle mCurrentImeHandle;
    private PendingIntent mKeyboardLayoutIntent;
    private Toast mSwitchedKeyboardLayoutToast;


    // State for vibrator tokens.
    // State for vibrator tokens.
    private Object mVibratorLock = new Object();
    private Object mVibratorLock = new Object();
@@ -1367,82 +1366,6 @@ public class InputManagerService extends IInputManager.Stub
        }
        }
    }
    }


    @Override // Binder call
    @Nullable
    public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            InputMethodInfo imeInfo, InputMethodSubtype imeSubtype) {
        InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(imeInfo, imeSubtype);
        String key = getLayoutDescriptor(identifier);
        final String keyboardLayoutDescriptor;
        synchronized (mDataStore) {
            keyboardLayoutDescriptor = mDataStore.getKeyboardLayout(key, handle);
        }

        if (keyboardLayoutDescriptor == null) {
            return null;
        }

        final KeyboardLayout[] result = new KeyboardLayout[1];
        visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
            @Override
            public void visitKeyboardLayout(Resources resources,
                    int keyboardLayoutResId, KeyboardLayout layout) {
                result[0] = layout;
            }
        });
        if (result[0] == null) {
            Slog.w(TAG, "Could not get keyboard layout with descriptor '"
                    + keyboardLayoutDescriptor + "'.");
        }
        return result[0];
    }

    @Override
    public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            InputMethodInfo imeInfo, InputMethodSubtype imeSubtype,
            String keyboardLayoutDescriptor) {
        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
                "setKeyboardLayoutForInputDevice()")) {
            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
        }
        if (keyboardLayoutDescriptor == null) {
            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
        }
        if (imeInfo == null || imeSubtype == null) {
            throw new IllegalArgumentException("imeInfo and imeSubtype must not be null");
        }
        InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(imeInfo, imeSubtype);
        setKeyboardLayoutForInputDeviceInner(identifier, handle, keyboardLayoutDescriptor);
    }

    private void setKeyboardLayoutForInputDeviceInner(InputDeviceIdentifier identifier,
            InputMethodSubtypeHandle imeHandle, String keyboardLayoutDescriptor) {
        String key = getLayoutDescriptor(identifier);
        synchronized (mDataStore) {
            try {
                if (mDataStore.setKeyboardLayout(key, imeHandle, keyboardLayoutDescriptor)) {
                    if (DEBUG) {
                        Slog.d(TAG, "Set keyboard layout " + keyboardLayoutDescriptor +
                                " for subtype " + imeHandle + " and device " + identifier +
                                " using key " + key);
                    }
                    if (imeHandle.equals(mCurrentImeHandle)) {
                        if (DEBUG) {
                            Slog.d(TAG, "Layout for current subtype changed, switching layout");
                        }
                        SomeArgs args = SomeArgs.obtain();
                        args.arg1 = identifier;
                        args.arg2 = imeHandle;
                        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, args).sendToTarget();
                    }
                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
                }
            } finally {
                mDataStore.saveIfNeeded();
            }
        }
    }

    @Override // Binder call
    @Override // Binder call
    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            String keyboardLayoutDescriptor) {
            String keyboardLayoutDescriptor) {
@@ -1462,7 +1385,8 @@ public class InputManagerService extends IInputManager.Stub
                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
                }
                }
                if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
                if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
                        && !Objects.equals(oldLayout, mDataStore.getCurrentKeyboardLayout(key))) {
                        && !Objects.equals(oldLayout,
                                mDataStore.getCurrentKeyboardLayout(key))) {
                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
                }
                }
            } finally {
            } finally {
@@ -1512,44 +1436,45 @@ public class InputManagerService extends IInputManager.Stub
            Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId
            Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId
                    + " ime=" + inputMethodInfo + " subtype=" + subtype);
                    + " ime=" + inputMethodInfo + " subtype=" + subtype);
        }
        }
        if (inputMethodInfo == null) {
            Slog.d(TAG, "No InputMethod is running, ignoring change");
            return;
        }
        if (subtype != null && !"keyboard".equals(subtype.getMode())) {
            Slog.d(TAG, "InputMethodSubtype changed to non-keyboard subtype, ignoring change");
            return;
        }
        InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(inputMethodInfo, subtype);
        if (!handle.equals(mCurrentImeHandle)) {
            mCurrentImeHandle = handle;
            handleSwitchKeyboardLayout(null, handle);
    }
    }

    public void switchKeyboardLayout(int deviceId, int direction) {
        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
    }
    }


    // Must be called on handler.
    // Must be called on handler.
    private void handleSwitchKeyboardLayout(@Nullable InputDeviceIdentifier identifier,
    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
            InputMethodSubtypeHandle handle) {
        final InputDevice device = getInputDevice(deviceId);
        synchronized (mInputDevicesLock) {
        if (device != null) {
            for (InputDevice device : mInputDevices) {
            final boolean changed;
                if (identifier != null && !device.getIdentifier().equals(identifier) ||
            final String keyboardLayoutDescriptor;
                        !device.isFullKeyboard()) {

                    continue;
                }
            String key = getLayoutDescriptor(device.getIdentifier());
            String key = getLayoutDescriptor(device.getIdentifier());
                boolean changed = false;
            synchronized (mDataStore) {
            synchronized (mDataStore) {
                try {
                try {
                        if (mDataStore.switchKeyboardLayout(key, handle)) {
                    changed = mDataStore.switchKeyboardLayout(key, direction);
                            changed = true;
                    keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
                        }
                            key);
                } finally {
                } finally {
                    mDataStore.saveIfNeeded();
                    mDataStore.saveIfNeeded();
                }
                }
            }
            }

            if (changed) {
            if (changed) {
                    reloadKeyboardLayouts();
                if (mSwitchedKeyboardLayoutToast != null) {
                    mSwitchedKeyboardLayoutToast.cancel();
                    mSwitchedKeyboardLayoutToast = null;
                }
                if (keyboardLayoutDescriptor != null) {
                    KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
                    if (keyboardLayout != null) {
                        mSwitchedKeyboardLayoutToast = Toast.makeText(
                                mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
                        mSwitchedKeyboardLayoutToast.show();
                    }
                }
                }

                reloadKeyboardLayouts();
            }
            }
        }
        }
    }
    }
@@ -1790,7 +1715,7 @@ public class InputManagerService extends IInputManager.Stub
    }
    }


    @Override
    @Override
    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;


        pw.println("INPUT MANAGER (dumpsys input)\n");
        pw.println("INPUT MANAGER (dumpsys input)\n");
@@ -1798,48 +1723,7 @@ public class InputManagerService extends IInputManager.Stub
        if (dumpStr != null) {
        if (dumpStr != null) {
            pw.println(dumpStr);
            pw.println(dumpStr);
        }
        }
        pw.println("  Keyboard Layouts:");
        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
            @Override
            public void visitKeyboardLayout(Resources resources,
                    int keyboardLayoutResId, KeyboardLayout layout) {
                pw.println("    \"" + layout + "\": " + layout.getDescriptor());
    }
    }
        });
        pw.println();
        synchronized(mDataStore) {
            mDataStore.dump(pw, "  ");
        }
    }

    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out,
            FileDescriptor err, String[] args, ShellCallback callback,
            ResultReceiver resultReceiver) {
        (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
    }

    public int onShellCommand(Shell shell, String cmd) {
        if (TextUtils.isEmpty(cmd)) {
            shell.onHelp();
            return 1;
        }
        if (cmd.equals("setlayout")) {
            if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
                    "onShellCommand()")) {
                throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
            }
            InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(
                    shell.getNextArgRequired(), Integer.parseInt(shell.getNextArgRequired()));
            String descriptor = shell.getNextArgRequired();
            int vid = Integer.decode(shell.getNextArgRequired());
            int pid = Integer.decode(shell.getNextArgRequired());
            InputDeviceIdentifier id = new InputDeviceIdentifier(descriptor, vid, pid);
            setKeyboardLayoutForInputDeviceInner(id, handle, shell.getNextArgRequired());
        }
        return 0;
    }



    private boolean checkCallingPermission(String permission, String func) {
    private boolean checkCallingPermission(String permission, String func) {
        // Quick check: if the calling permission is me, it's all okay.
        // Quick check: if the calling permission is me, it's all okay.
@@ -2169,12 +2053,9 @@ public class InputManagerService extends IInputManager.Stub
                case MSG_DELIVER_INPUT_DEVICES_CHANGED:
                case MSG_DELIVER_INPUT_DEVICES_CHANGED:
                    deliverInputDevicesChanged((InputDevice[])msg.obj);
                    deliverInputDevicesChanged((InputDevice[])msg.obj);
                    break;
                    break;
                case MSG_SWITCH_KEYBOARD_LAYOUT: {
                case MSG_SWITCH_KEYBOARD_LAYOUT:
                    SomeArgs args = (SomeArgs)msg.obj;
                    handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
                    handleSwitchKeyboardLayout((InputDeviceIdentifier)args.arg1,
                            (InputMethodSubtypeHandle)args.arg2);
                    break;
                    break;
                }
                case MSG_RELOAD_KEYBOARD_LAYOUTS:
                case MSG_RELOAD_KEYBOARD_LAYOUTS:
                    reloadKeyboardLayouts();
                    reloadKeyboardLayouts();
                    break;
                    break;
@@ -2341,25 +2222,6 @@ public class InputManagerService extends IInputManager.Stub
        }
        }
    }
    }


    private class Shell extends ShellCommand {
        @Override
        public int onCommand(String cmd) {
            return onShellCommand(this, cmd);
        }

        @Override
        public void onHelp() {
            final PrintWriter pw = getOutPrintWriter();
            pw.println("Input manager commands:");
            pw.println("  help");
            pw.println("    Print this help text.");
            pw.println("");
            pw.println("  setlayout IME_ID IME_SUPTYPE_HASH_CODE"
                    + " DEVICE_DESCRIPTOR VENDOR_ID PRODUCT_ID KEYBOARD_DESCRIPTOR");
            pw.println("    Sets a keyboard layout for a given IME subtype and input device pair");
        }
    }

    private final class LocalService extends InputManagerInternal {
    private final class LocalService extends InputManagerInternal {
        @Override
        @Override
        public void setDisplayViewports(DisplayViewport defaultViewport,
        public void setDisplayViewports(DisplayViewport defaultViewport,
Loading