diff options
9 files changed, 102 insertions, 444 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index 9e0c680cafa1..97868fa268ad 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -26,8 +26,6 @@ import android.os.IBinder; import android.view.InputDevice; import android.view.InputEvent; import android.view.PointerIcon; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodSubtype; /** @hide */ interface IInputManager { @@ -67,11 +65,6 @@ interface IInputManager { String keyboardLayoutDescriptor); void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier, 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. void registerInputDevicesChangedListener(IInputDevicesChangedListener listener); diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 87895f7e612e..6ae7a146a7b7 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -42,8 +42,6 @@ import android.view.InputDevice; import android.view.InputEvent; import android.view.MotionEvent; import android.view.PointerIcon; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodSubtype; 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. * diff --git a/core/java/android/hardware/input/TouchCalibration.java b/core/java/android/hardware/input/TouchCalibration.java index 15503ed0b900..025fad046eb8 100644 --- a/core/java/android/hardware/input/TouchCalibration.java +++ b/core/java/android/hardware/input/TouchCalibration.java @@ -123,10 +123,4 @@ public class TouchCalibration implements Parcelable { Float.floatToIntBits(mYScale) ^ Float.floatToIntBits(mYOffset); } - - @Override - public String toString() { - return String.format("[%f, %f, %f, %f, %f, %f]", - mXScale, mXYMix, mXOffset, mYXMix, mYScale, mYOffset); - } } diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeHandle.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeHandle.java deleted file mode 100644 index 975021e85cce..000000000000 --- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeHandle.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 + "}"; - } -} diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 620f2ca3fc58..a70909ff4158 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -22,7 +22,6 @@ import android.os.LocaleList; import android.os.ShellCallback; import android.util.Log; import android.view.Display; -import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.SomeArgs; @@ -79,8 +78,6 @@ import android.os.Message; import android.os.MessageQueue; import android.os.Process; import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.ShellCommand; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -101,6 +98,7 @@ import android.view.Surface; import android.view.ViewConfiguration; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; +import android.widget.Toast; import java.io.File; import java.io.FileDescriptor; @@ -174,7 +172,8 @@ public class InputManagerService extends IInputManager.Stub private final ArrayList<InputDevice> mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only private boolean mKeyboardLayoutNotificationShown; - private InputMethodSubtypeHandle mCurrentImeHandle; + private PendingIntent mKeyboardLayoutIntent; + private Toast mSwitchedKeyboardLayoutToast; // State for vibrator tokens. private Object mVibratorLock = new Object(); @@ -1368,82 +1367,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 public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor) { if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT, @@ -1462,7 +1385,8 @@ public class InputManagerService extends IInputManager.Stub oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor()); } if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor) - && !Objects.equals(oldLayout, mDataStore.getCurrentKeyboardLayout(key))) { + && !Objects.equals(oldLayout, + mDataStore.getCurrentKeyboardLayout(key))) { mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS); } } finally { @@ -1512,44 +1436,45 @@ public class InputManagerService extends IInputManager.Stub Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId + " 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. - private void handleSwitchKeyboardLayout(@Nullable InputDeviceIdentifier identifier, - InputMethodSubtypeHandle handle) { - synchronized (mInputDevicesLock) { - for (InputDevice device : mInputDevices) { - if (identifier != null && !device.getIdentifier().equals(identifier) || - !device.isFullKeyboard()) { - continue; + private void handleSwitchKeyboardLayout(int deviceId, int direction) { + final InputDevice device = getInputDevice(deviceId); + if (device != null) { + final boolean changed; + final String keyboardLayoutDescriptor; + + String key = getLayoutDescriptor(device.getIdentifier()); + synchronized (mDataStore) { + try { + changed = mDataStore.switchKeyboardLayout(key, direction); + keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout( + key); + } finally { + mDataStore.saveIfNeeded(); } - String key = getLayoutDescriptor(device.getIdentifier()); - boolean changed = false; - synchronized (mDataStore) { - try { - if (mDataStore.switchKeyboardLayout(key, handle)) { - changed = true; - } - } finally { - mDataStore.saveIfNeeded(); - } + } + + if (changed) { + if (mSwitchedKeyboardLayoutToast != null) { + mSwitchedKeyboardLayoutToast.cancel(); + mSwitchedKeyboardLayoutToast = null; } - if (changed) { - reloadKeyboardLayouts(); + 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 - 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; pw.println("INPUT MANAGER (dumpsys input)\n"); @@ -1798,49 +1723,8 @@ public class InputManagerService extends IInputManager.Stub if (dumpStr != null) { 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) { // Quick check: if the calling permission is me, it's all okay. if (Binder.getCallingPid() == Process.myPid()) { @@ -2169,12 +2053,9 @@ public class InputManagerService extends IInputManager.Stub case MSG_DELIVER_INPUT_DEVICES_CHANGED: deliverInputDevicesChanged((InputDevice[])msg.obj); break; - case MSG_SWITCH_KEYBOARD_LAYOUT: { - SomeArgs args = (SomeArgs)msg.obj; - handleSwitchKeyboardLayout((InputDeviceIdentifier)args.arg1, - (InputMethodSubtypeHandle)args.arg2); + case MSG_SWITCH_KEYBOARD_LAYOUT: + handleSwitchKeyboardLayout(msg.arg1, msg.arg2); break; - } case MSG_RELOAD_KEYBOARD_LAYOUTS: reloadKeyboardLayouts(); 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 { @Override public void setDisplayViewports(DisplayViewport defaultViewport, diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java index c9f8b2084697..196787aa5cda 100644 --- a/services/core/java/com/android/server/input/PersistentDataStore.java +++ b/services/core/java/com/android/server/input/PersistentDataStore.java @@ -16,7 +16,6 @@ package com.android.server.input; -import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; @@ -28,8 +27,6 @@ import org.xmlpull.v1.XmlSerializer; import android.annotation.Nullable; import android.view.Surface; import android.hardware.input.TouchCalibration; -import android.text.TextUtils; -import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Slog; import android.util.Xml; @@ -41,13 +38,10 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -139,26 +133,9 @@ final class PersistentDataStore { } return state.getKeyboardLayouts(); } - public String getKeyboardLayout(String inputDeviceDescriptor, - InputMethodSubtypeHandle imeHandle) { - InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false); - if (state == null) { - return null; - } - return state.getKeyboardLayout(imeHandle); - } - public boolean setKeyboardLayout(String inputDeviceDescriptor, - InputMethodSubtypeHandle imeHandle, String keyboardLayoutDescriptor) { - InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true); - if (state.setKeyboardLayout(imeHandle, keyboardLayoutDescriptor)) { - setDirty(); - return true; - } - return false; - } - - public boolean addKeyboardLayout(String inputDeviceDescriptor, String keyboardLayoutDescriptor) { + public boolean addKeyboardLayout(String inputDeviceDescriptor, + String keyboardLayoutDescriptor) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true); if (state.addKeyboardLayout(keyboardLayoutDescriptor)) { setDirty(); @@ -177,10 +154,9 @@ final class PersistentDataStore { return false; } - public boolean switchKeyboardLayout(String inputDeviceDescriptor, - InputMethodSubtypeHandle imeHandle) { + public boolean switchKeyboardLayout(String inputDeviceDescriptor, int direction) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false); - if (state != null && state.switchKeyboardLayout(imeHandle)) { + if (state != null && state.switchKeyboardLayout(direction)) { setDirty(); return true; } @@ -327,18 +303,6 @@ final class PersistentDataStore { serializer.endDocument(); } - public void dump(PrintWriter pw, String prefix) { - pw.println(prefix + "PersistentDataStore"); - pw.println(prefix + " mLoaded=" + mLoaded); - pw.println(prefix + " mDirty=" + mDirty); - pw.println(prefix + " InputDeviceStates:"); - int i = 0; - for (Map.Entry<String, InputDeviceState> entry : mInputDevices.entrySet()) { - pw.println(prefix + " " + i++ + ": " + entry.getKey()); - entry.getValue().dump(pw, prefix + " "); - } - } - private static final class InputDeviceState { private static final String[] CALIBRATION_NAME = { "x_scale", "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" }; @@ -346,8 +310,7 @@ final class PersistentDataStore { private TouchCalibration[] mTouchCalibration = new TouchCalibration[4]; @Nullable private String mCurrentKeyboardLayout; - private List<String> mUnassociatedKeyboardLayouts = new ArrayList<>(); - private ArrayMap<InputMethodSubtypeHandle, String> mKeyboardLayouts = new ArrayMap<>(); + private ArrayList<String> mKeyboardLayouts = new ArrayList<String>(); public TouchCalibration getTouchCalibration(int surfaceRotation) { try { @@ -386,34 +349,18 @@ final class PersistentDataStore { } public String[] getKeyboardLayouts() { - if (mUnassociatedKeyboardLayouts.isEmpty()) { + if (mKeyboardLayouts.isEmpty()) { return (String[])ArrayUtils.emptyArray(String.class); } - return mUnassociatedKeyboardLayouts.toArray( - new String[mUnassociatedKeyboardLayouts.size()]); - } - - public String getKeyboardLayout(InputMethodSubtypeHandle handle) { - return mKeyboardLayouts.get(handle); - } - - public boolean setKeyboardLayout(InputMethodSubtypeHandle imeHandle, - String keyboardLayout) { - String existingLayout = mKeyboardLayouts.get(imeHandle); - if (TextUtils.equals(existingLayout, keyboardLayout)) { - return false; - } - mKeyboardLayouts.put(imeHandle, keyboardLayout); - return true; + return mKeyboardLayouts.toArray(new String[mKeyboardLayouts.size()]); } public boolean addKeyboardLayout(String keyboardLayout) { - int index = Collections.binarySearch( - mUnassociatedKeyboardLayouts, keyboardLayout); + int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout); if (index >= 0) { return false; } - mUnassociatedKeyboardLayouts.add(-index - 1, keyboardLayout); + mKeyboardLayouts.add(-index - 1, keyboardLayout); if (mCurrentKeyboardLayout == null) { mCurrentKeyboardLayout = keyboardLayout; } @@ -421,11 +368,11 @@ final class PersistentDataStore { } public boolean removeKeyboardLayout(String keyboardLayout) { - int index = Collections.binarySearch(mUnassociatedKeyboardLayouts, keyboardLayout); + int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout); if (index < 0) { return false; } - mUnassociatedKeyboardLayouts.remove(index); + mKeyboardLayouts.remove(index); updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, index); return true; } @@ -433,34 +380,41 @@ final class PersistentDataStore { private void updateCurrentKeyboardLayoutIfRemoved( String removedKeyboardLayout, int removedIndex) { if (Objects.equals(mCurrentKeyboardLayout, removedKeyboardLayout)) { - if (!mUnassociatedKeyboardLayouts.isEmpty()) { + if (!mKeyboardLayouts.isEmpty()) { int index = removedIndex; - if (index == mUnassociatedKeyboardLayouts.size()) { + if (index == mKeyboardLayouts.size()) { index = 0; } - mCurrentKeyboardLayout = mUnassociatedKeyboardLayouts.get(index); + mCurrentKeyboardLayout = mKeyboardLayouts.get(index); } else { mCurrentKeyboardLayout = null; } } } - public boolean switchKeyboardLayout(InputMethodSubtypeHandle imeHandle) { - final String layout = mKeyboardLayouts.get(imeHandle); - if (!TextUtils.equals(mCurrentKeyboardLayout, layout)) { - mCurrentKeyboardLayout = layout; - return true; + public boolean switchKeyboardLayout(int direction) { + final int size = mKeyboardLayouts.size(); + if (size < 2) { + return false; + } + int index = Collections.binarySearch(mKeyboardLayouts, mCurrentKeyboardLayout); + assert index >= 0; + if (direction > 0) { + index = (index + 1) % size; + } else { + index = (index + size - 1) % size; } - return false; + mCurrentKeyboardLayout = mKeyboardLayouts.get(index); + return true; } public boolean removeUninstalledKeyboardLayouts(Set<String> availableKeyboardLayouts) { boolean changed = false; - for (int i = mUnassociatedKeyboardLayouts.size(); i-- > 0; ) { - String keyboardLayout = mUnassociatedKeyboardLayouts.get(i); + for (int i = mKeyboardLayouts.size(); i-- > 0; ) { + String keyboardLayout = mKeyboardLayouts.get(i); if (!availableKeyboardLayouts.contains(keyboardLayout)) { Slog.i(TAG, "Removing uninstalled keyboard layout " + keyboardLayout); - mUnassociatedKeyboardLayouts.remove(i); + mKeyboardLayouts.remove(i); updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, i); changed = true; } @@ -478,8 +432,13 @@ final class PersistentDataStore { throw new XmlPullParserException( "Missing descriptor attribute on keyboard-layout."); } - String current = parser.getAttributeValue(null, "current"); + if (mKeyboardLayouts.contains(descriptor)) { + throw new XmlPullParserException( + "Found duplicate keyboard layout."); + } + + mKeyboardLayouts.add(descriptor); if (current != null && current.equals("true")) { if (mCurrentKeyboardLayout != null) { throw new XmlPullParserException( @@ -487,32 +446,6 @@ final class PersistentDataStore { } mCurrentKeyboardLayout = descriptor; } - - String inputMethodId = parser.getAttributeValue(null, "input-method-id"); - String inputMethodSubtypeId = - parser.getAttributeValue(null, "input-method-subtype-id"); - if (inputMethodId == null && inputMethodSubtypeId != null - || inputMethodId != null && inputMethodSubtypeId == null) { - throw new XmlPullParserException( - "Found an incomplete input method description"); - } - - if (inputMethodSubtypeId != null) { - InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle( - inputMethodId, Integer.parseInt(inputMethodSubtypeId)); - if (mKeyboardLayouts.containsKey(handle)) { - throw new XmlPullParserException( - "Found duplicate subtype to keyboard layout mapping: " - + handle); - } - mKeyboardLayouts.put(handle, descriptor); - } else { - if (mUnassociatedKeyboardLayouts.contains(descriptor)) { - throw new XmlPullParserException( - "Found duplicate unassociated keyboard layout: " + descriptor); - } - mUnassociatedKeyboardLayouts.add(descriptor); - } } else if (parser.getName().equals("calibration")) { String format = parser.getAttributeValue(null, "format"); String rotation = parser.getAttributeValue(null, "rotation"); @@ -563,31 +496,19 @@ final class PersistentDataStore { } // Maintain invariant that layouts are sorted. - Collections.sort(mUnassociatedKeyboardLayouts); + Collections.sort(mKeyboardLayouts); // Maintain invariant that there is always a current keyboard layout unless // there are none installed. - if (mCurrentKeyboardLayout == null && !mUnassociatedKeyboardLayouts.isEmpty()) { - mCurrentKeyboardLayout = mUnassociatedKeyboardLayouts.get(0); + if (mCurrentKeyboardLayout == null && !mKeyboardLayouts.isEmpty()) { + mCurrentKeyboardLayout = mKeyboardLayouts.get(0); } } public void saveToXml(XmlSerializer serializer) throws IOException { - for (String layout : mUnassociatedKeyboardLayouts) { - serializer.startTag(null, "keyboard-layout"); - serializer.attribute(null, "descriptor", layout); - serializer.endTag(null, "keyboard-layout"); - } - - final int N = mKeyboardLayouts.size(); - for (int i = 0; i < N; i++) { - final InputMethodSubtypeHandle handle = mKeyboardLayouts.keyAt(i); - final String layout = mKeyboardLayouts.valueAt(i); + for (String layout : mKeyboardLayouts) { serializer.startTag(null, "keyboard-layout"); serializer.attribute(null, "descriptor", layout); - serializer.attribute(null, "input-method-id", handle.getInputMethodId()); - serializer.attribute(null, "input-method-subtype-id", - Integer.toString(handle.getSubtypeId())); if (layout.equals(mCurrentKeyboardLayout)) { serializer.attribute(null, "current", "true"); } @@ -612,22 +533,6 @@ final class PersistentDataStore { } } - private void dump(final PrintWriter pw, final String prefix) { - pw.println(prefix + "CurrentKeyboardLayout=" + mCurrentKeyboardLayout); - pw.println(prefix + "UnassociatedKeyboardLayouts=" + mUnassociatedKeyboardLayouts); - pw.println(prefix + "TouchCalibration=" + Arrays.toString(mTouchCalibration)); - pw.println(prefix + "Subtype to Layout Mappings:"); - final int N = mKeyboardLayouts.size(); - if (N != 0) { - for (int i = 0; i < N; i++) { - pw.println(prefix + " " + mKeyboardLayouts.keyAt(i) + ": " - + mKeyboardLayouts.valueAt(i)); - } - } else { - pw.println(prefix + " <none>"); - } - } - private static String surfaceRotationToString(int surfaceRotation) { switch (surfaceRotation) { case Surface.ROTATION_0: return "0"; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 8bc9830f49d5..810ec11b3860 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3860,6 +3860,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { hideRecentApps(true, false); } + // Handle keyboard layout switching. + // TODO: Deprecate this behavior when we fully migrate to IME subtype-based layout rotation. + if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_SPACE + && ((metaState & KeyEvent.META_CTRL_MASK) != 0)) { + int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; + mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction); + return -1; + } + // Handle input method switching. if (down && repeatCount == 0 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index d5c12f73cacb..0a6f70a58dd6 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -545,6 +545,12 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public int getCameraLensCoverState(); /** + * Switch the keyboard layout for the given device. + * Direction should be +1 or -1 to go to the next or previous keyboard layout. + */ + public void switchKeyboardLayout(int deviceId, int direction); + + /** * Switch the input method, to be precise, input method subtype. * * @param forwardDirection {@code true} to rotate in a forward direction. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2041c6fc72d6..26b47dde59b2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3178,6 +3178,12 @@ public class WindowManagerService extends IWindowManager.Stub // Called by window manager policy. Not exposed externally. @Override + public void switchKeyboardLayout(int deviceId, int direction) { + mInputManager.switchKeyboardLayout(deviceId, direction); + } + + // Called by window manager policy. Not exposed externally. + @Override public void switchInputMethod(boolean forwardDirection) { final InputMethodManagerInternal inputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class); |