diff options
| -rw-r--r-- | services/core/java/com/android/server/inputmethod/InputMethodManagerService.java | 19 | ||||
| -rw-r--r-- | services/core/java/com/android/server/inputmethod/InputMethodMenuController.java | 240 |
2 files changed, 132 insertions, 127 deletions
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index c4d94ee93235..4f998ee2cfa2 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -276,7 +276,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final Context mContext; final Resources mRes; private final Handler mHandler; - final InputMethodSettings mSettings; + private final InputMethodSettings mSettings; final SettingsObserver mSettingsObserver; private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid = new SparseBooleanArray(0); @@ -316,7 +316,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // Mapping from deviceId to the device-specific imeId for that device. private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>(); - final InputMethodSubtypeSwitchingController mSwitchingController; + private final InputMethodSubtypeSwitchingController mSwitchingController; final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController(); @@ -4812,7 +4812,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); return false; } - mMenuController.showInputMethodMenu(showAuxSubtypes, displayId); + synchronized (ImfLock.class) { + final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked() + && mWindowManagerInternal.isKeyguardSecure( + mSettings.getCurrentUserId()); + final String lastInputMethodId = mSettings.getSelectedInputMethod(); + int lastInputMethodSubtypeId = + mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); + + final List<ImeSubtypeListItem> imList = mSwitchingController + .getSortedInputMethodAndSubtypeListForImeMenuLocked( + showAuxSubtypes, isScreenLocked); + mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId, + lastInputMethodId, lastInputMethodSubtypeId, imList); + } return true; // --------------------------------------------------------- diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java index bc3643abb86c..6ed4848c20b4 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java @@ -19,6 +19,7 @@ package com.android.server.inputmethod; import static com.android.server.inputmethod.InputMethodManagerService.DEBUG; import static com.android.server.inputmethod.InputMethodUtils.NOT_A_SUBTYPE_ID; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlertDialog; import android.content.Context; @@ -52,8 +53,6 @@ final class InputMethodMenuController { private static final String TAG = InputMethodMenuController.class.getSimpleName(); private final InputMethodManagerService mService; - private final InputMethodUtils.InputMethodSettings mSettings; - private final InputMethodSubtypeSwitchingController mSwitchingController; private final WindowManagerInternal mWindowManagerInternal; private AlertDialog.Builder mDialogBuilder; @@ -70,142 +69,135 @@ final class InputMethodMenuController { InputMethodMenuController(InputMethodManagerService service) { mService = service; - mSettings = mService.mSettings; - mSwitchingController = mService.mSwitchingController; mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); } - void showInputMethodMenu(boolean showAuxSubtypes, int displayId) { + @GuardedBy("ImfLock.class") + void showInputMethodMenuLocked(boolean showAuxSubtypes, int displayId, + String preferredInputMethodId, int preferredInputMethodSubtypeId, + @NonNull List<ImeSubtypeListItem> imList) { if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes); - synchronized (ImfLock.class) { - final int userId = mService.getCurrentImeUserIdLocked(); - final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked() - && mWindowManagerInternal.isKeyguardSecure(userId); - final String lastInputMethodId = mSettings.getSelectedInputMethod(); - int lastInputMethodSubtypeId = - mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); - if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId); - - final List<ImeSubtypeListItem> imList = mSwitchingController - .getSortedInputMethodAndSubtypeListForImeMenuLocked( - showAuxSubtypes, isScreenLocked); - if (imList.isEmpty()) { - return; - } + final int userId = mService.getCurrentImeUserIdLocked(); - hideInputMethodMenuLocked(); + if (imList.isEmpty()) { + return; + } - if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { - final InputMethodSubtype currentSubtype = - mService.getCurrentInputMethodSubtypeLocked(); - if (currentSubtype != null) { - final String curMethodId = mService.getSelectedMethodIdLocked(); - final InputMethodInfo currentImi = - mService.queryInputMethodForCurrentUserLocked(curMethodId); - lastInputMethodSubtypeId = SubtypeUtils.getSubtypeIdFromHashCode( - currentImi, currentSubtype.hashCode()); - } + hideInputMethodMenuLocked(); + + if (preferredInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { + final InputMethodSubtype currentSubtype = + mService.getCurrentInputMethodSubtypeLocked(); + if (currentSubtype != null) { + final String curMethodId = mService.getSelectedMethodIdLocked(); + final InputMethodInfo currentImi = + mService.queryInputMethodForCurrentUserLocked(curMethodId); + preferredInputMethodSubtypeId = SubtypeUtils.getSubtypeIdFromHashCode( + currentImi, currentSubtype.hashCode()); } + } - final int size = imList.size(); - mIms = new InputMethodInfo[size]; - mSubtypeIds = new int[size]; - int checkedItem = 0; - for (int i = 0; i < size; ++i) { - final ImeSubtypeListItem item = imList.get(i); - mIms[i] = item.mImi; - mSubtypeIds[i] = item.mSubtypeId; - if (mIms[i].getId().equals(lastInputMethodId)) { - int subtypeId = mSubtypeIds[i]; - if ((subtypeId == NOT_A_SUBTYPE_ID) - || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0) - || (subtypeId == lastInputMethodSubtypeId)) { - checkedItem = i; - } + // Find out which item should be checked by default. + final int size = imList.size(); + mIms = new InputMethodInfo[size]; + mSubtypeIds = new int[size]; + int checkedItem = 0; + for (int i = 0; i < size; ++i) { + final ImeSubtypeListItem item = imList.get(i); + mIms[i] = item.mImi; + mSubtypeIds[i] = item.mSubtypeId; + if (mIms[i].getId().equals(preferredInputMethodId)) { + int subtypeId = mSubtypeIds[i]; + if ((subtypeId == NOT_A_SUBTYPE_ID) + || (preferredInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0) + || (subtypeId == preferredInputMethodSubtypeId)) { + checkedItem = i; } } + } - if (mDialogWindowContext == null) { - mDialogWindowContext = new InputMethodDialogWindowContext(); - } - final Context dialogWindowContext = mDialogWindowContext.get(displayId); - mDialogBuilder = new AlertDialog.Builder(dialogWindowContext); - mDialogBuilder.setOnCancelListener(dialog -> hideInputMethodMenu()); - - final Context dialogContext = mDialogBuilder.getContext(); - final TypedArray a = dialogContext.obtainStyledAttributes(null, - com.android.internal.R.styleable.DialogPreference, - com.android.internal.R.attr.alertDialogStyle, 0); - final Drawable dialogIcon = a.getDrawable( - com.android.internal.R.styleable.DialogPreference_dialogIcon); - a.recycle(); - - mDialogBuilder.setIcon(dialogIcon); - - final LayoutInflater inflater = dialogContext.getSystemService(LayoutInflater.class); - final View tv = inflater.inflate( - com.android.internal.R.layout.input_method_switch_dialog_title, null); - mDialogBuilder.setCustomTitle(tv); - - // Setup layout for a toggle switch of the hardware keyboard - mSwitchingDialogTitleView = tv; - mSwitchingDialogTitleView - .findViewById(com.android.internal.R.id.hard_keyboard_section) - .setVisibility(mWindowManagerInternal.isHardKeyboardAvailable() - ? View.VISIBLE : View.GONE); - final Switch hardKeySwitch = mSwitchingDialogTitleView.findViewById( - com.android.internal.R.id.hard_keyboard_switch); - hardKeySwitch.setChecked(mShowImeWithHardKeyboard); - hardKeySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { - SecureSettingsWrapper.putBoolean(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, - isChecked, userId); - // Ensure that the input method dialog is dismissed when changing - // the hardware keyboard state. - hideInputMethodMenu(); - }); - - final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(dialogContext, - com.android.internal.R.layout.input_method_switch_item, imList, checkedItem); - final DialogInterface.OnClickListener choiceListener = (dialog, which) -> { - synchronized (ImfLock.class) { - if (mIms == null || mIms.length <= which || mSubtypeIds == null - || mSubtypeIds.length <= which) { - return; - } - final InputMethodInfo im = mIms[which]; - int subtypeId = mSubtypeIds[which]; - adapter.mCheckedItem = which; - adapter.notifyDataSetChanged(); - if (im != null) { - if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) { - subtypeId = NOT_A_SUBTYPE_ID; - } - mService.setInputMethodLocked(im.getId(), subtypeId); + if (mDialogWindowContext == null) { + mDialogWindowContext = new InputMethodDialogWindowContext(); + } + final Context dialogWindowContext = mDialogWindowContext.get(displayId); + mDialogBuilder = new AlertDialog.Builder(dialogWindowContext); + mDialogBuilder.setOnCancelListener(dialog -> hideInputMethodMenu()); + + final Context dialogContext = mDialogBuilder.getContext(); + final TypedArray a = dialogContext.obtainStyledAttributes(null, + com.android.internal.R.styleable.DialogPreference, + com.android.internal.R.attr.alertDialogStyle, 0); + final Drawable dialogIcon = a.getDrawable( + com.android.internal.R.styleable.DialogPreference_dialogIcon); + a.recycle(); + + mDialogBuilder.setIcon(dialogIcon); + + final LayoutInflater inflater = dialogContext.getSystemService(LayoutInflater.class); + final View tv = inflater.inflate( + com.android.internal.R.layout.input_method_switch_dialog_title, null); + mDialogBuilder.setCustomTitle(tv); + + // Setup layout for a toggle switch of the hardware keyboard + mSwitchingDialogTitleView = tv; + mSwitchingDialogTitleView + .findViewById(com.android.internal.R.id.hard_keyboard_section) + .setVisibility(mWindowManagerInternal.isHardKeyboardAvailable() + ? View.VISIBLE : View.GONE); + final Switch hardKeySwitch = mSwitchingDialogTitleView.findViewById( + com.android.internal.R.id.hard_keyboard_switch); + hardKeySwitch.setChecked(mShowImeWithHardKeyboard); + hardKeySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + SecureSettingsWrapper.putBoolean(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, + isChecked, userId); + // Ensure that the input method dialog is dismissed when changing + // the hardware keyboard state. + hideInputMethodMenu(); + }); + + // Fill the list items with onClick listener, which takes care of IME (and subtype) + // switching when clicked. + final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(dialogContext, + com.android.internal.R.layout.input_method_switch_item, imList, checkedItem); + final DialogInterface.OnClickListener choiceListener = (dialog, which) -> { + synchronized (ImfLock.class) { + if (mIms == null || mIms.length <= which || mSubtypeIds == null + || mSubtypeIds.length <= which) { + return; + } + final InputMethodInfo im = mIms[which]; + int subtypeId = mSubtypeIds[which]; + adapter.mCheckedItem = which; + adapter.notifyDataSetChanged(); + if (im != null) { + if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) { + subtypeId = NOT_A_SUBTYPE_ID; } - hideInputMethodMenuLocked(); + mService.setInputMethodLocked(im.getId(), subtypeId); } - }; - mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener); - - mSwitchingDialog = mDialogBuilder.create(); - mSwitchingDialog.setCanceledOnTouchOutside(true); - final Window w = mSwitchingDialog.getWindow(); - final WindowManager.LayoutParams attrs = w.getAttributes(); - w.setType(WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG); - w.setHideOverlayWindows(true); - // Use an alternate token for the dialog for that window manager can group the token - // with other IME windows based on type vs. grouping based on whichever token happens - // to get selected by the system later on. - attrs.token = dialogWindowContext.getWindowContextToken(); - attrs.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; - attrs.setTitle("Select input method"); - w.setAttributes(attrs); - mService.updateSystemUiLocked(); - mService.sendOnNavButtonFlagsChangedLocked(); - mSwitchingDialog.show(); - - } + hideInputMethodMenuLocked(); + } + }; + mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener); + + // Final steps to instantiate a dialog to show it up. + mSwitchingDialog = mDialogBuilder.create(); + mSwitchingDialog.setCanceledOnTouchOutside(true); + final Window w = mSwitchingDialog.getWindow(); + final WindowManager.LayoutParams attrs = w.getAttributes(); + w.setType(WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG); + w.setHideOverlayWindows(true); + // Use an alternate token for the dialog for that window manager can group the token + // with other IME windows based on type vs. grouping based on whichever token happens + // to get selected by the system later on. + attrs.token = dialogWindowContext.getWindowContextToken(); + attrs.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; + attrs.setTitle("Select input method"); + w.setAttributes(attrs); + mService.updateSystemUiLocked(); + mService.sendOnNavButtonFlagsChangedLocked(); + mSwitchingDialog.show(); } void updateKeyboardFromSettingsLocked() { |