Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +29 −280 Original line number Original line Diff line number Diff line Loading @@ -37,8 +37,6 @@ import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal; import android.app.ActivityThread; import android.app.AlertDialog; import android.app.AppGlobals; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.KeyguardManager; import android.app.KeyguardManager; Loading @@ -50,9 +48,6 @@ import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.ServiceConnection; Loading @@ -64,10 +59,8 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.database.ContentObserver; import android.graphics.Matrix; import android.graphics.Matrix; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal; import android.hardware.input.InputManagerInternal; import android.hardware.input.InputManagerInternal; import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService; Loading Loading @@ -108,14 +101,10 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseArray; import android.util.imetracing.ImeTracing; import android.util.imetracing.ImeTracing; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream; import android.view.ContextThemeWrapper; import android.view.DisplayInfo; import android.view.DisplayInfo; import android.view.IWindowManager; import android.view.IWindowManager; import android.view.InputChannel; import android.view.InputChannel; import android.view.LayoutInflater; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.autofill.AutofillId; import android.view.autofill.AutofillId; Loading @@ -129,12 +118,6 @@ import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype; import android.widget.ArrayAdapter; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.RadioButton; import android.widget.Switch; import android.widget.TextView; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.content.PackageMonitor; Loading Loading @@ -165,7 +148,6 @@ import com.android.internal.view.InputBindResult; import com.android.server.EventLogTags; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener; import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings; import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings; Loading Loading @@ -330,10 +312,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap = private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap = new ArrayMap<>(); new ArrayMap<>(); private final boolean mIsLowRam; private final boolean mIsLowRam; private final HardKeyboardListener mHardKeyboardListener; private final AppOpsManager mAppOpsManager; private final AppOpsManager mAppOpsManager; private final UserManager mUserManager; private final UserManager mUserManager; private final UserManagerInternal mUserManagerInternal; private final UserManagerInternal mUserManagerInternal; private final InputMethodMenuController mMenuController; /** /** * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}. * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}. Loading @@ -351,7 +333,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans = private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans = new LruCache<>(SECURE_SUGGESTION_SPANS_MAX_SIZE); new LruCache<>(SECURE_SUGGESTION_SPANS_MAX_SIZE); private final InputMethodSubtypeSwitchingController mSwitchingController; final InputMethodSubtypeSwitchingController mSwitchingController; /** /** * Tracks how many times {@link #mMethodMap} was updated. * Tracks how many times {@link #mMethodMap} was updated. Loading Loading @@ -380,7 +362,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Ongoing notification // Ongoing notification private NotificationManager mNotificationManager; private NotificationManager mNotificationManager; private KeyguardManager mKeyguardManager; KeyguardManager mKeyguardManager; private @Nullable StatusBarManagerService mStatusBar; private @Nullable StatusBarManagerService mStatusBar; private Notification.Builder mImeSwitcherNotification; private Notification.Builder mImeSwitcherNotification; private PendingIntent mImeSwitchPendingIntent; private PendingIntent mImeSwitchPendingIntent; Loading Loading @@ -724,21 +706,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ */ int mImeWindowVis; int mImeWindowVis; private AlertDialog.Builder mDialogBuilder; private AlertDialog mSwitchingDialog; private IBinder mSwitchingDialogToken = new Binder(); private View mSwitchingDialogTitleView; private InputMethodInfo[] mIms; private int[] mSubtypeIds; private LocaleList mLastSystemLocales; private LocaleList mLastSystemLocales; private boolean mShowImeWithHardKeyboard; private boolean mAccessibilityRequestingNoSoftKeyboard; private boolean mAccessibilityRequestingNoSoftKeyboard; private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor(); private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor(); private final IPackageManager mIPackageManager; private final IPackageManager mIPackageManager; private final String mSlotIme; private final String mSlotIme; /** /** * Registered {@link InputMethodListListeners}. * Registered {@link InputMethodListListener}. * This variable can be accessed from both of MainThread and BinderThread. * This variable can be accessed from both of MainThread and BinderThread. */ */ private final CopyOnWriteArrayList<InputMethodListListener> mInputMethodListListeners = private final CopyOnWriteArrayList<InputMethodListListener> mInputMethodListListeners = Loading Loading @@ -1138,7 +1113,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); synchronized (mMethodMap) { synchronized (mMethodMap) { if (showImeUri.equals(uri)) { if (showImeUri.equals(uri)) { updateKeyboardFromSettingsLocked(); mMenuController.updateKeyboardFromSettingsLocked(); } else if (accessibilityRequestingNoImeUri.equals(uri)) { } else if (accessibilityRequestingNoImeUri.equals(uri)) { final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser( final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser( mContext.getContentResolver(), mContext.getContentResolver(), Loading Loading @@ -1226,7 +1201,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; return; } } } } hideInputMethodMenu(); mMenuController.hideInputMethodMenu(); } else { } else { Slog.w(TAG, "Unexpected intent " + intent); Slog.w(TAG, "Unexpected intent " + intent); } } Loading Loading @@ -1526,29 +1501,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } private class HardKeyboardListener implements WindowManagerInternal.OnHardKeyboardStatusChangeListener { @Override public void onHardKeyboardStatusChange(boolean available) { mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0)); } public void handleHardKeyboardStatusChange(boolean available) { if (DEBUG) { Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available); } synchronized(mMethodMap) { if (mSwitchingDialog != null && mSwitchingDialogTitleView != null && mSwitchingDialog.isShowing()) { mSwitchingDialogTitleView.findViewById( com.android.internal.R.id.hard_keyboard_section).setVisibility( available ? View.VISIBLE : View.GONE); } } } } private static final class UserSwitchHandlerTask implements Runnable { private static final class UserSwitchHandlerTask implements Runnable { final InputMethodManagerService mService; final InputMethodManagerService mService; Loading Loading @@ -1687,7 +1639,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mUserManager = mContext.getSystemService(UserManager.class); mUserManager = mContext.getSystemService(UserManager.class); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mHardKeyboardListener = new HardKeyboardListener(); mHasFeature = context.getPackageManager().hasSystemFeature( mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS); PackageManager.FEATURE_INPUT_METHODS); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); Loading Loading @@ -1731,6 +1682,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId); AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mSettings, context); mSettings, context); mMenuController = new InputMethodMenuController(this); } } private void resetDefaultImeLocked(Context context) { private void resetDefaultImeLocked(Context context) { Loading Loading @@ -1861,8 +1813,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mShowOngoingImeSwitcherForPhones = mRes.getBoolean( mShowOngoingImeSwitcherForPhones = mRes.getBoolean( com.android.internal.R.bool.show_ongoing_ime_switcher); com.android.internal.R.bool.show_ongoing_ime_switcher); if (mShowOngoingImeSwitcherForPhones) { if (mShowOngoingImeSwitcherForPhones) { final InputMethodMenuController.HardKeyboardListener hardKeyboardListener = mMenuController.getHardKeyboardListener(); mWindowManagerInternal.setOnHardKeyboardStatusChangeListener( mWindowManagerInternal.setOnHardKeyboardStatusChangeListener( mHardKeyboardListener); hardKeyboardListener); } } mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true); mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true); Loading Loading @@ -2331,7 +2285,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurClient = null; mCurClient = null; mCurActivityViewToScreenMatrix = null; mCurActivityViewToScreenMatrix = null; hideInputMethodMenuLocked(); mMenuController.hideInputMethodMenuLocked(); } } } } Loading Loading @@ -2813,7 +2767,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private boolean shouldShowImeSwitcherLocked(int visibility) { private boolean shouldShowImeSwitcherLocked(int visibility) { if (!mShowOngoingImeSwitcherForPhones) return false; if (!mShowOngoingImeSwitcherForPhones) return false; if (mSwitchingDialog != null) return false; if (mMenuController.getSwitchingDialogLocked() != null) return false; if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded() if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded() && mKeyguardManager != null && mKeyguardManager.isKeyguardSecure()) return false; && mKeyguardManager != null && mKeyguardManager.isKeyguardSecure()) return false; if ((visibility & InputMethodService.IME_ACTIVE) == 0 if ((visibility & InputMethodService.IME_ACTIVE) == 0 Loading Loading @@ -2930,6 +2884,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } void updateSystemUiLocked() { updateSystemUiLocked(mImeWindowVis, mBackDisposition); } // Caution! This method is called in this class. Handle multi-user carefully // Caution! This method is called in this class. Handle multi-user carefully private void updateSystemUiLocked(int vis, int backDisposition) { private void updateSystemUiLocked(int vis, int backDisposition) { if (mCurToken == null) { if (mCurToken == null) { Loading Loading @@ -3000,7 +2958,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void updateFromSettingsLocked(boolean enabledMayChange) { void updateFromSettingsLocked(boolean enabledMayChange) { updateInputMethodsFromSettingsLocked(enabledMayChange); updateInputMethodsFromSettingsLocked(enabledMayChange); updateKeyboardFromSettingsLocked(); mMenuController.updateKeyboardFromSettingsLocked(); } } void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) { void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) { Loading Loading @@ -3057,17 +3015,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } public void updateKeyboardFromSettingsLocked() { mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled(); if (mSwitchingDialog != null && mSwitchingDialogTitleView != null && mSwitchingDialog.isShowing()) { final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById( com.android.internal.R.id.hard_keyboard_switch); hardKeySwitch.setChecked(mShowImeWithHardKeyboard); } } /* package */ void setInputMethodLocked(String id, int subtypeId) { /* package */ void setInputMethodLocked(String id, int subtypeId) { InputMethodInfo info = mMethodMap.get(id); InputMethodInfo info = mMethodMap.get(id); if (info == null) { if (info == null) { Loading Loading @@ -3697,10 +3644,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public boolean isInputMethodPickerShownForTest() { public boolean isInputMethodPickerShownForTest() { synchronized(mMethodMap) { synchronized(mMethodMap) { if (mSwitchingDialog == null) { return mMenuController.isisInputMethodPickerShownForTestLocked(); return false; } return mSwitchingDialog.isShowing(); } } } } Loading Loading @@ -3935,7 +3879,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * {@link InputMethodService#onCreate()}. * {@link InputMethodService#onCreate()}. * * * <p>TODO(Bug 113914148): Check if we can remove this.</p> * <p>TODO(Bug 113914148): Check if we can remove this.</p> * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()} * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight(int)} */ */ @Override @Override public int getInputMethodWindowVisibleHeight() { public int getInputMethodWindowVisibleHeight() { Loading Loading @@ -4247,7 +4191,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); return false; return false; } } showInputMethodMenu(showAuxSubtypes, displayId); mMenuController.showInputMethodMenu(showAuxSubtypes, displayId); return true; return true; case MSG_SHOW_IM_SUBTYPE_ENABLER: case MSG_SHOW_IM_SUBTYPE_ENABLER: Loading Loading @@ -4484,7 +4428,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // -------------------------------------------------------------- // -------------------------------------------------------------- case MSG_HARD_KEYBOARD_SWITCH_CHANGED: case MSG_HARD_KEYBOARD_SWITCH_CHANGED: mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1); final InputMethodMenuController.HardKeyboardListener hardKeyboardListener = mMenuController.getHardKeyboardListener(); hardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1); return true; return true; case MSG_SYSTEM_UNLOCK_USER: { case MSG_SYSTEM_UNLOCK_USER: { final int userId = msg.arg1; final int userId = msg.arg1; Loading Loading @@ -4735,208 +4681,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mContext.startActivityAsUser(intent, null, UserHandle.CURRENT); mContext.startActivityAsUser(intent, null, UserHandle.CURRENT); } } private boolean isScreenLocked() { return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure(); } private void showInputMethodMenu(boolean showAuxSubtypes, int displayId) { if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes); final boolean isScreenLocked = isScreenLocked(); final String lastInputMethodId = mSettings.getSelectedInputMethod(); int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId); synchronized (mMethodMap) { final List<ImeSubtypeListItem> imList = mSwitchingController.getSortedInputMethodAndSubtypeListLocked( showAuxSubtypes, isScreenLocked); if (imList.isEmpty()) { return; } hideInputMethodMenuLocked(); if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked(); if (currentSubtype != null) { final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId); lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode( currentImi, currentSubtype.hashCode()); } } final int N = imList.size(); mIms = new InputMethodInfo[N]; mSubtypeIds = new int[N]; int checkedItem = 0; for (int i = 0; i < N; ++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; } } } final ActivityThread currentThread = ActivityThread.currentActivityThread(); final Context settingsContext = new ContextThemeWrapper( displayId == DEFAULT_DISPLAY ? currentThread.getSystemUiContext() : currentThread.createSystemUiContext(displayId), com.android.internal.R.style.Theme_DeviceDefault_Settings); mDialogBuilder = new AlertDialog.Builder(settingsContext); mDialogBuilder.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface 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 = (Switch) mSwitchingDialogTitleView.findViewById( com.android.internal.R.id.hard_keyboard_switch); hardKeySwitch.setChecked(mShowImeWithHardKeyboard); hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mSettings.setShowImeWithHardKeyboard(isChecked); // 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 OnClickListener choiceListener = new OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { synchronized (mMethodMap) { 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(); hideInputMethodMenu(); if (im != null) { if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) { subtypeId = NOT_A_SUBTYPE_ID; } setInputMethodLocked(im.getId(), subtypeId); } } } }; mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener); mSwitchingDialog = mDialogBuilder.create(); mSwitchingDialog.setCanceledOnTouchOutside(true); final Window w = mSwitchingDialog.getWindow(); final LayoutParams attrs = w.getAttributes(); w.setType(LayoutParams.TYPE_INPUT_METHOD_DIALOG); // 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 = mSwitchingDialogToken; attrs.privateFlags |= LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; attrs.setTitle("Select input method"); w.setAttributes(attrs); updateSystemUiLocked(mImeWindowVis, mBackDisposition); mSwitchingDialog.show(); } } private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> { private final LayoutInflater mInflater; private final int mTextViewResourceId; private final List<ImeSubtypeListItem> mItemsList; public int mCheckedItem; public ImeSubtypeListAdapter(Context context, int textViewResourceId, List<ImeSubtypeListItem> itemsList, int checkedItem) { super(context, textViewResourceId, itemsList); mTextViewResourceId = textViewResourceId; mItemsList = itemsList; mCheckedItem = checkedItem; mInflater = context.getSystemService(LayoutInflater.class); } @Override public View getView(int position, View convertView, ViewGroup parent) { final View view = convertView != null ? convertView : mInflater.inflate(mTextViewResourceId, null); if (position < 0 || position >= mItemsList.size()) return view; final ImeSubtypeListItem item = mItemsList.get(position); final CharSequence imeName = item.mImeName; final CharSequence subtypeName = item.mSubtypeName; final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1); final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2); if (TextUtils.isEmpty(subtypeName)) { firstTextView.setText(imeName); secondTextView.setVisibility(View.GONE); } else { firstTextView.setText(subtypeName); secondTextView.setText(imeName); secondTextView.setVisibility(View.VISIBLE); } final RadioButton radioButton = (RadioButton)view.findViewById(com.android.internal.R.id.radio); radioButton.setChecked(position == mCheckedItem); return view; } } void hideInputMethodMenu() { synchronized (mMethodMap) { hideInputMethodMenuLocked(); } } void hideInputMethodMenuLocked() { if (DEBUG) Slog.v(TAG, "Hide switching menu"); if (mSwitchingDialog != null) { mSwitchingDialog.dismiss(); mSwitchingDialog = null; mSwitchingDialogTitleView = null; } updateSystemUiLocked(mImeWindowVis, mBackDisposition); mDialogBuilder = null; mIms = null; } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- /** /** Loading Loading @@ -5040,7 +4784,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } private InputMethodSubtype getCurrentInputMethodSubtypeLocked() { InputMethodSubtype getCurrentInputMethodSubtypeLocked() { if (mCurMethodId == null) { if (mCurMethodId == null) { return null; return null; } } Loading Loading @@ -5079,6 +4823,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return mCurrentSubtype; return mCurrentSubtype; } } @Nullable String getCurrentMethodId() { return mCurMethodId; } private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) { private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) { synchronized (mMethodMap) { synchronized (mMethodMap) { return getInputMethodListLocked(userId); return getInputMethodListLocked(userId); Loading services/core/java/com/android/server/inputmethod/InputMethodMenuController.java 0 → 100644 +327 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +29 −280 Original line number Original line Diff line number Diff line Loading @@ -37,8 +37,6 @@ import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal; import android.app.ActivityThread; import android.app.AlertDialog; import android.app.AppGlobals; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.KeyguardManager; import android.app.KeyguardManager; Loading @@ -50,9 +48,6 @@ import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.ServiceConnection; Loading @@ -64,10 +59,8 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.database.ContentObserver; import android.graphics.Matrix; import android.graphics.Matrix; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal; import android.hardware.input.InputManagerInternal; import android.hardware.input.InputManagerInternal; import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService; Loading Loading @@ -108,14 +101,10 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseArray; import android.util.imetracing.ImeTracing; import android.util.imetracing.ImeTracing; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream; import android.view.ContextThemeWrapper; import android.view.DisplayInfo; import android.view.DisplayInfo; import android.view.IWindowManager; import android.view.IWindowManager; import android.view.InputChannel; import android.view.InputChannel; import android.view.LayoutInflater; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.autofill.AutofillId; import android.view.autofill.AutofillId; Loading @@ -129,12 +118,6 @@ import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype; import android.widget.ArrayAdapter; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.RadioButton; import android.widget.Switch; import android.widget.TextView; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.content.PackageMonitor; Loading Loading @@ -165,7 +148,6 @@ import com.android.internal.view.InputBindResult; import com.android.server.EventLogTags; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener; import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings; import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings; Loading Loading @@ -330,10 +312,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap = private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap = new ArrayMap<>(); new ArrayMap<>(); private final boolean mIsLowRam; private final boolean mIsLowRam; private final HardKeyboardListener mHardKeyboardListener; private final AppOpsManager mAppOpsManager; private final AppOpsManager mAppOpsManager; private final UserManager mUserManager; private final UserManager mUserManager; private final UserManagerInternal mUserManagerInternal; private final UserManagerInternal mUserManagerInternal; private final InputMethodMenuController mMenuController; /** /** * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}. * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}. Loading @@ -351,7 +333,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans = private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans = new LruCache<>(SECURE_SUGGESTION_SPANS_MAX_SIZE); new LruCache<>(SECURE_SUGGESTION_SPANS_MAX_SIZE); private final InputMethodSubtypeSwitchingController mSwitchingController; final InputMethodSubtypeSwitchingController mSwitchingController; /** /** * Tracks how many times {@link #mMethodMap} was updated. * Tracks how many times {@link #mMethodMap} was updated. Loading Loading @@ -380,7 +362,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Ongoing notification // Ongoing notification private NotificationManager mNotificationManager; private NotificationManager mNotificationManager; private KeyguardManager mKeyguardManager; KeyguardManager mKeyguardManager; private @Nullable StatusBarManagerService mStatusBar; private @Nullable StatusBarManagerService mStatusBar; private Notification.Builder mImeSwitcherNotification; private Notification.Builder mImeSwitcherNotification; private PendingIntent mImeSwitchPendingIntent; private PendingIntent mImeSwitchPendingIntent; Loading Loading @@ -724,21 +706,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ */ int mImeWindowVis; int mImeWindowVis; private AlertDialog.Builder mDialogBuilder; private AlertDialog mSwitchingDialog; private IBinder mSwitchingDialogToken = new Binder(); private View mSwitchingDialogTitleView; private InputMethodInfo[] mIms; private int[] mSubtypeIds; private LocaleList mLastSystemLocales; private LocaleList mLastSystemLocales; private boolean mShowImeWithHardKeyboard; private boolean mAccessibilityRequestingNoSoftKeyboard; private boolean mAccessibilityRequestingNoSoftKeyboard; private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor(); private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor(); private final IPackageManager mIPackageManager; private final IPackageManager mIPackageManager; private final String mSlotIme; private final String mSlotIme; /** /** * Registered {@link InputMethodListListeners}. * Registered {@link InputMethodListListener}. * This variable can be accessed from both of MainThread and BinderThread. * This variable can be accessed from both of MainThread and BinderThread. */ */ private final CopyOnWriteArrayList<InputMethodListListener> mInputMethodListListeners = private final CopyOnWriteArrayList<InputMethodListListener> mInputMethodListListeners = Loading Loading @@ -1138,7 +1113,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); synchronized (mMethodMap) { synchronized (mMethodMap) { if (showImeUri.equals(uri)) { if (showImeUri.equals(uri)) { updateKeyboardFromSettingsLocked(); mMenuController.updateKeyboardFromSettingsLocked(); } else if (accessibilityRequestingNoImeUri.equals(uri)) { } else if (accessibilityRequestingNoImeUri.equals(uri)) { final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser( final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser( mContext.getContentResolver(), mContext.getContentResolver(), Loading Loading @@ -1226,7 +1201,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; return; } } } } hideInputMethodMenu(); mMenuController.hideInputMethodMenu(); } else { } else { Slog.w(TAG, "Unexpected intent " + intent); Slog.w(TAG, "Unexpected intent " + intent); } } Loading Loading @@ -1526,29 +1501,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } private class HardKeyboardListener implements WindowManagerInternal.OnHardKeyboardStatusChangeListener { @Override public void onHardKeyboardStatusChange(boolean available) { mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0)); } public void handleHardKeyboardStatusChange(boolean available) { if (DEBUG) { Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available); } synchronized(mMethodMap) { if (mSwitchingDialog != null && mSwitchingDialogTitleView != null && mSwitchingDialog.isShowing()) { mSwitchingDialogTitleView.findViewById( com.android.internal.R.id.hard_keyboard_section).setVisibility( available ? View.VISIBLE : View.GONE); } } } } private static final class UserSwitchHandlerTask implements Runnable { private static final class UserSwitchHandlerTask implements Runnable { final InputMethodManagerService mService; final InputMethodManagerService mService; Loading Loading @@ -1687,7 +1639,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mUserManager = mContext.getSystemService(UserManager.class); mUserManager = mContext.getSystemService(UserManager.class); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mHardKeyboardListener = new HardKeyboardListener(); mHasFeature = context.getPackageManager().hasSystemFeature( mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS); PackageManager.FEATURE_INPUT_METHODS); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); Loading Loading @@ -1731,6 +1682,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId); AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mSettings, context); mSettings, context); mMenuController = new InputMethodMenuController(this); } } private void resetDefaultImeLocked(Context context) { private void resetDefaultImeLocked(Context context) { Loading Loading @@ -1861,8 +1813,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mShowOngoingImeSwitcherForPhones = mRes.getBoolean( mShowOngoingImeSwitcherForPhones = mRes.getBoolean( com.android.internal.R.bool.show_ongoing_ime_switcher); com.android.internal.R.bool.show_ongoing_ime_switcher); if (mShowOngoingImeSwitcherForPhones) { if (mShowOngoingImeSwitcherForPhones) { final InputMethodMenuController.HardKeyboardListener hardKeyboardListener = mMenuController.getHardKeyboardListener(); mWindowManagerInternal.setOnHardKeyboardStatusChangeListener( mWindowManagerInternal.setOnHardKeyboardStatusChangeListener( mHardKeyboardListener); hardKeyboardListener); } } mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true); mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true); Loading Loading @@ -2331,7 +2285,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurClient = null; mCurClient = null; mCurActivityViewToScreenMatrix = null; mCurActivityViewToScreenMatrix = null; hideInputMethodMenuLocked(); mMenuController.hideInputMethodMenuLocked(); } } } } Loading Loading @@ -2813,7 +2767,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private boolean shouldShowImeSwitcherLocked(int visibility) { private boolean shouldShowImeSwitcherLocked(int visibility) { if (!mShowOngoingImeSwitcherForPhones) return false; if (!mShowOngoingImeSwitcherForPhones) return false; if (mSwitchingDialog != null) return false; if (mMenuController.getSwitchingDialogLocked() != null) return false; if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded() if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded() && mKeyguardManager != null && mKeyguardManager.isKeyguardSecure()) return false; && mKeyguardManager != null && mKeyguardManager.isKeyguardSecure()) return false; if ((visibility & InputMethodService.IME_ACTIVE) == 0 if ((visibility & InputMethodService.IME_ACTIVE) == 0 Loading Loading @@ -2930,6 +2884,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } void updateSystemUiLocked() { updateSystemUiLocked(mImeWindowVis, mBackDisposition); } // Caution! This method is called in this class. Handle multi-user carefully // Caution! This method is called in this class. Handle multi-user carefully private void updateSystemUiLocked(int vis, int backDisposition) { private void updateSystemUiLocked(int vis, int backDisposition) { if (mCurToken == null) { if (mCurToken == null) { Loading Loading @@ -3000,7 +2958,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void updateFromSettingsLocked(boolean enabledMayChange) { void updateFromSettingsLocked(boolean enabledMayChange) { updateInputMethodsFromSettingsLocked(enabledMayChange); updateInputMethodsFromSettingsLocked(enabledMayChange); updateKeyboardFromSettingsLocked(); mMenuController.updateKeyboardFromSettingsLocked(); } } void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) { void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) { Loading Loading @@ -3057,17 +3015,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } public void updateKeyboardFromSettingsLocked() { mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled(); if (mSwitchingDialog != null && mSwitchingDialogTitleView != null && mSwitchingDialog.isShowing()) { final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById( com.android.internal.R.id.hard_keyboard_switch); hardKeySwitch.setChecked(mShowImeWithHardKeyboard); } } /* package */ void setInputMethodLocked(String id, int subtypeId) { /* package */ void setInputMethodLocked(String id, int subtypeId) { InputMethodInfo info = mMethodMap.get(id); InputMethodInfo info = mMethodMap.get(id); if (info == null) { if (info == null) { Loading Loading @@ -3697,10 +3644,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public boolean isInputMethodPickerShownForTest() { public boolean isInputMethodPickerShownForTest() { synchronized(mMethodMap) { synchronized(mMethodMap) { if (mSwitchingDialog == null) { return mMenuController.isisInputMethodPickerShownForTestLocked(); return false; } return mSwitchingDialog.isShowing(); } } } } Loading Loading @@ -3935,7 +3879,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * {@link InputMethodService#onCreate()}. * {@link InputMethodService#onCreate()}. * * * <p>TODO(Bug 113914148): Check if we can remove this.</p> * <p>TODO(Bug 113914148): Check if we can remove this.</p> * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()} * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight(int)} */ */ @Override @Override public int getInputMethodWindowVisibleHeight() { public int getInputMethodWindowVisibleHeight() { Loading Loading @@ -4247,7 +4191,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); return false; return false; } } showInputMethodMenu(showAuxSubtypes, displayId); mMenuController.showInputMethodMenu(showAuxSubtypes, displayId); return true; return true; case MSG_SHOW_IM_SUBTYPE_ENABLER: case MSG_SHOW_IM_SUBTYPE_ENABLER: Loading Loading @@ -4484,7 +4428,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // -------------------------------------------------------------- // -------------------------------------------------------------- case MSG_HARD_KEYBOARD_SWITCH_CHANGED: case MSG_HARD_KEYBOARD_SWITCH_CHANGED: mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1); final InputMethodMenuController.HardKeyboardListener hardKeyboardListener = mMenuController.getHardKeyboardListener(); hardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1); return true; return true; case MSG_SYSTEM_UNLOCK_USER: { case MSG_SYSTEM_UNLOCK_USER: { final int userId = msg.arg1; final int userId = msg.arg1; Loading Loading @@ -4735,208 +4681,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mContext.startActivityAsUser(intent, null, UserHandle.CURRENT); mContext.startActivityAsUser(intent, null, UserHandle.CURRENT); } } private boolean isScreenLocked() { return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure(); } private void showInputMethodMenu(boolean showAuxSubtypes, int displayId) { if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes); final boolean isScreenLocked = isScreenLocked(); final String lastInputMethodId = mSettings.getSelectedInputMethod(); int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId); synchronized (mMethodMap) { final List<ImeSubtypeListItem> imList = mSwitchingController.getSortedInputMethodAndSubtypeListLocked( showAuxSubtypes, isScreenLocked); if (imList.isEmpty()) { return; } hideInputMethodMenuLocked(); if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked(); if (currentSubtype != null) { final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId); lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode( currentImi, currentSubtype.hashCode()); } } final int N = imList.size(); mIms = new InputMethodInfo[N]; mSubtypeIds = new int[N]; int checkedItem = 0; for (int i = 0; i < N; ++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; } } } final ActivityThread currentThread = ActivityThread.currentActivityThread(); final Context settingsContext = new ContextThemeWrapper( displayId == DEFAULT_DISPLAY ? currentThread.getSystemUiContext() : currentThread.createSystemUiContext(displayId), com.android.internal.R.style.Theme_DeviceDefault_Settings); mDialogBuilder = new AlertDialog.Builder(settingsContext); mDialogBuilder.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface 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 = (Switch) mSwitchingDialogTitleView.findViewById( com.android.internal.R.id.hard_keyboard_switch); hardKeySwitch.setChecked(mShowImeWithHardKeyboard); hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mSettings.setShowImeWithHardKeyboard(isChecked); // 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 OnClickListener choiceListener = new OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { synchronized (mMethodMap) { 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(); hideInputMethodMenu(); if (im != null) { if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) { subtypeId = NOT_A_SUBTYPE_ID; } setInputMethodLocked(im.getId(), subtypeId); } } } }; mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener); mSwitchingDialog = mDialogBuilder.create(); mSwitchingDialog.setCanceledOnTouchOutside(true); final Window w = mSwitchingDialog.getWindow(); final LayoutParams attrs = w.getAttributes(); w.setType(LayoutParams.TYPE_INPUT_METHOD_DIALOG); // 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 = mSwitchingDialogToken; attrs.privateFlags |= LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; attrs.setTitle("Select input method"); w.setAttributes(attrs); updateSystemUiLocked(mImeWindowVis, mBackDisposition); mSwitchingDialog.show(); } } private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> { private final LayoutInflater mInflater; private final int mTextViewResourceId; private final List<ImeSubtypeListItem> mItemsList; public int mCheckedItem; public ImeSubtypeListAdapter(Context context, int textViewResourceId, List<ImeSubtypeListItem> itemsList, int checkedItem) { super(context, textViewResourceId, itemsList); mTextViewResourceId = textViewResourceId; mItemsList = itemsList; mCheckedItem = checkedItem; mInflater = context.getSystemService(LayoutInflater.class); } @Override public View getView(int position, View convertView, ViewGroup parent) { final View view = convertView != null ? convertView : mInflater.inflate(mTextViewResourceId, null); if (position < 0 || position >= mItemsList.size()) return view; final ImeSubtypeListItem item = mItemsList.get(position); final CharSequence imeName = item.mImeName; final CharSequence subtypeName = item.mSubtypeName; final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1); final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2); if (TextUtils.isEmpty(subtypeName)) { firstTextView.setText(imeName); secondTextView.setVisibility(View.GONE); } else { firstTextView.setText(subtypeName); secondTextView.setText(imeName); secondTextView.setVisibility(View.VISIBLE); } final RadioButton radioButton = (RadioButton)view.findViewById(com.android.internal.R.id.radio); radioButton.setChecked(position == mCheckedItem); return view; } } void hideInputMethodMenu() { synchronized (mMethodMap) { hideInputMethodMenuLocked(); } } void hideInputMethodMenuLocked() { if (DEBUG) Slog.v(TAG, "Hide switching menu"); if (mSwitchingDialog != null) { mSwitchingDialog.dismiss(); mSwitchingDialog = null; mSwitchingDialogTitleView = null; } updateSystemUiLocked(mImeWindowVis, mBackDisposition); mDialogBuilder = null; mIms = null; } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- /** /** Loading Loading @@ -5040,7 +4784,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } private InputMethodSubtype getCurrentInputMethodSubtypeLocked() { InputMethodSubtype getCurrentInputMethodSubtypeLocked() { if (mCurMethodId == null) { if (mCurMethodId == null) { return null; return null; } } Loading Loading @@ -5079,6 +4823,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return mCurrentSubtype; return mCurrentSubtype; } } @Nullable String getCurrentMethodId() { return mCurMethodId; } private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) { private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) { synchronized (mMethodMap) { synchronized (mMethodMap) { return getInputMethodListLocked(userId); return getInputMethodListLocked(userId); Loading
services/core/java/com/android/server/inputmethod/InputMethodMenuController.java 0 → 100644 +327 −0 File added.Preview size limit exceeded, changes collapsed. Show changes