Loading core/java/android/provider/Settings.java +14 −0 Original line number Diff line number Diff line Loading @@ -7427,6 +7427,20 @@ public final class Settings { @Readable public static final String DEFAULT_INPUT_METHOD = "default_input_method"; /** * Used only by {@link com.android.server.inputmethod.InputMethodManagerService} as a * temporary data store of {@link #DEFAULT_INPUT_METHOD} while a virtual-device-specific * input method is set as default.</p> * * <p>This should be considered to be an implementation detail of * {@link com.android.server.inputmethod.InputMethodManagerService}. Other system * components should never rely on this value.</p> * * @see #DEFAULT_INPUT_METHOD * @hide */ public static final String DEFAULT_DEVICE_INPUT_METHOD = "default_device_input_method"; /** * Setting to record the input method subtype used by default, holding the ID * of the desired method. Loading packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -686,6 +686,7 @@ public class SettingsBackupTest { Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, Settings.Secure.CONTENT_CAPTURE_ENABLED, Settings.Secure.DEFAULT_INPUT_METHOD, Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, Settings.Secure.DEVICE_PAIRED, Settings.Secure.DIALER_DEFAULT_APPLICATION, Settings.Secure.DISABLED_PRINT_SERVICES, Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +111 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.inputmethod; import static android.content.Context.DEVICE_ID_DEFAULT; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; import static android.os.IServiceManager.DUMP_FLAG_PROTO; Loading Loading @@ -315,7 +316,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // All known input methods. final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>(); private final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); // Mapping from deviceId to the device-specific imeId for that device. @GuardedBy("ImfLock.class") private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>(); private final InputMethodSubtypeSwitchingController mSwitchingController; Loading @@ -339,6 +342,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private int mDisplayIdToShowIme = INVALID_DISPLAY; @GuardedBy("ImfLock.class") private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT; @Nullable private StatusBarManagerInternal mStatusBarManagerInternal; private boolean mShowOngoingImeSwitcherForPhones; @GuardedBy("ImfLock.class") Loading Loading @@ -2464,11 +2470,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @StartInputReason int startInputReason, int unverifiedTargetSdkVersion, @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { // If no method is currently selected, do nothing. final String selectedMethodId = getSelectedMethodIdLocked(); if (selectedMethodId == null) { return InputBindResult.NO_IME; } String selectedMethodId = getSelectedMethodIdLocked(); if (!mSystemReady) { // If the system is not yet ready, we shouldn't be running third Loading @@ -2493,8 +2495,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return InputBindResult.NOT_IME_TARGET_WINDOW; } final int csDisplayId = cs.mSelfReportedDisplayId; final int oldDisplayIdToShowIme = mDisplayIdToShowIme; mDisplayIdToShowIme = mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId); // Potentially override the selected input method if the new display belongs to a virtual // device with a custom IME. if (oldDisplayIdToShowIme != mDisplayIdToShowIme) { final String deviceMethodId = computeCurrentDeviceMethodIdLocked(selectedMethodId); if (deviceMethodId == null) { mVisibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true); } else if (!Objects.equals(deviceMethodId, selectedMethodId)) { setInputMethodLocked(deviceMethodId, NOT_A_SUBTYPE_ID, mDeviceIdToShowIme); selectedMethodId = deviceMethodId; } } if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) { hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, null /* resultReceiver */, Loading @@ -2502,6 +2517,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return InputBindResult.NO_IME; } // If no method is currently selected, do nothing. if (selectedMethodId == null) { return InputBindResult.NO_IME; } if (mCurClient != cs) { prepareClientSwitchLocked(cs); } Loading Loading @@ -2568,6 +2588,62 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mBindingController.bindCurrentMethod(); } /** * Update the current deviceId and return the relevant imeId for this device. * 1. If the device changes to virtual and its custom IME is not available, then disable IME. * 2. If the device changes to virtual with valid custom IME, then return the custom IME. If * the old device was default, then store the current imeId so it can be restored. * 3. If the device changes to default, restore the default device IME. * 4. Otherwise keep the current imeId. */ @GuardedBy("ImfLock.class") private String computeCurrentDeviceMethodIdLocked(String currentMethodId) { if (mVdmInternal == null) { mVdmInternal = LocalServices.getService(VirtualDeviceManagerInternal.class); } if (mVdmInternal == null || !android.companion.virtual.flags.Flags.vdmCustomIme()) { return currentMethodId; } final int oldDeviceId = mDeviceIdToShowIme; mDeviceIdToShowIme = mVdmInternal.getDeviceIdForDisplayId(mDisplayIdToShowIme); if (mDeviceIdToShowIme == oldDeviceId) { return currentMethodId; } if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) { final String defaultDeviceMethodId = mSettings.getSelectedDefaultDeviceInputMethod(); if (DEBUG) { Slog.v(TAG, "Restoring default device input method: " + defaultDeviceMethodId); } return defaultDeviceMethodId; } final String deviceMethodId = mVirtualDeviceMethodMap.get(mDeviceIdToShowIme, currentMethodId); if (Objects.equals(deviceMethodId, currentMethodId)) { return currentMethodId; } else if (!mMethodMap.containsKey(deviceMethodId)) { if (DEBUG) { Slog.v(TAG, "Disabling IME on virtual device with id " + mDeviceIdToShowIme + " because its custom input method is not available: " + deviceMethodId); } return null; } if (oldDeviceId == DEVICE_ID_DEFAULT) { if (DEBUG) { Slog.v(TAG, "Storing default device input method " + currentMethodId); } mSettings.putSelectedDefaultDeviceInputMethod(currentMethodId); } if (DEBUG) { Slog.v(TAG, "Switching current input method from " + currentMethodId + " to device-specific one " + deviceMethodId + " because the current display " + mDisplayIdToShowIme + " belongs to device with id " + mDeviceIdToShowIme); } return deviceMethodId; } @GuardedBy("ImfLock.class") void invalidateAutofillSessionLocked() { mAutofillController.invalidateAutofillSession(); Loading Loading @@ -3242,6 +3318,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") void setInputMethodLocked(String id, int subtypeId) { setInputMethodLocked(id, subtypeId, DEVICE_ID_DEFAULT); } @GuardedBy("ImfLock.class") void setInputMethodLocked(String id, int subtypeId, int deviceId) { InputMethodInfo info = mMethodMap.get(id); if (info == null) { throw getExceptionForUnknownImeId(id); Loading Loading @@ -3285,6 +3366,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } // Changing to a different IME. if (mDeviceIdToShowIme != DEVICE_ID_DEFAULT && deviceId == DEVICE_ID_DEFAULT) { // This change should only be applicable to the default device but the current input // method is a custom one specific to a virtual device. So only update the settings // entry used to restore the default device input method once we want to show the IME // back on the default device. mSettings.putSelectedDefaultDeviceInputMethod(id); return; } IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { curMethod.removeStylusHandwritingWindow(); Loading Loading @@ -5308,12 +5397,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub StringBuilder builder = new StringBuilder(); if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( builder, enabledInputMethodsList, id)) { if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) { // Disabled input method is currently selected, switch to another one. final String selId = mSettings.getSelectedInputMethod(); if (id.equals(selId) && !chooseNewDefaultIMELocked()) { Slog.i(TAG, "Can't find new IME, unsetting the current input method."); resetSelectedInputMethodAndSubtypeLocked(""); } } else if (id.equals(mSettings.getSelectedDefaultDeviceInputMethod())) { // Disabled default device IME while using a virtual device one, choose a // new default one but only update the settings. InputMethodInfo newDefaultIme = InputMethodInfoUtils.getMostApplicableDefaultIME( mSettings.getEnabledInputMethodListLocked()); mSettings.putSelectedDefaultDeviceInputMethod( newDefaultIme == null ? "" : newDefaultIme.getId()); } // Previous state was enabled. return true; } else { Loading Loading @@ -5652,9 +5751,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @Override public void setVirtualDeviceInputMethodForAllUsers(int deviceId, @Nullable String imeId) { // TODO(b/287269288): validate that id belongs to a valid virtual device instead. Preconditions.checkArgument(deviceId != Context.DEVICE_ID_DEFAULT, "DeviceId " + deviceId + " does not belong to a virtual device."); Preconditions.checkArgument(deviceId != DEVICE_ID_DEFAULT, TextUtils.formatSimple("DeviceId %d is not a virtual device id.", deviceId)); synchronized (ImfLock.class) { if (imeId == null) { mVirtualDeviceMethodMap.remove(deviceId); Loading services/core/java/com/android/server/inputmethod/InputMethodUtils.java +25 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import com.android.server.textservices.TextServicesManagerInternal; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Predicate; Loading Loading @@ -241,6 +242,12 @@ final class InputMethodUtils { Slog.d(TAG, "--- Switch the current user from " + mCurrentUserId + " to " + userId); } mCurrentUserId = userId; String ime = getSelectedInputMethod(); String defaultDeviceIme = getSelectedDefaultDeviceInputMethod(); if (defaultDeviceIme != null && !Objects.equals(ime, defaultDeviceIme)) { putSelectedInputMethod(defaultDeviceIme); putSelectedDefaultDeviceInputMethod(null); } } private void putString(@NonNull String key, @Nullable String str) { Loading Loading @@ -636,6 +643,24 @@ final class InputMethodUtils { return imi; } @Nullable String getSelectedDefaultDeviceInputMethod() { final String imi = getString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null); if (DEBUG) { Slog.d(TAG, "getSelectedDefaultDeviceInputMethodStr: " + imi + ", " + mCurrentUserId); } return imi; } void putSelectedDefaultDeviceInputMethod(String imeId) { if (DEBUG) { Slog.d(TAG, "putSelectedDefaultDeviceInputMethodStr: " + imeId + ", " + mCurrentUserId); } putString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, imeId); } void putDefaultVoiceInputMethod(String imeId) { if (DEBUG) { Slog.d(TAG, "putDefaultVoiceInputMethodStr: " + imeId + ", " + mCurrentUserId); Loading Loading
core/java/android/provider/Settings.java +14 −0 Original line number Diff line number Diff line Loading @@ -7427,6 +7427,20 @@ public final class Settings { @Readable public static final String DEFAULT_INPUT_METHOD = "default_input_method"; /** * Used only by {@link com.android.server.inputmethod.InputMethodManagerService} as a * temporary data store of {@link #DEFAULT_INPUT_METHOD} while a virtual-device-specific * input method is set as default.</p> * * <p>This should be considered to be an implementation detail of * {@link com.android.server.inputmethod.InputMethodManagerService}. Other system * components should never rely on this value.</p> * * @see #DEFAULT_INPUT_METHOD * @hide */ public static final String DEFAULT_DEVICE_INPUT_METHOD = "default_device_input_method"; /** * Setting to record the input method subtype used by default, holding the ID * of the desired method. Loading
packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -686,6 +686,7 @@ public class SettingsBackupTest { Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, Settings.Secure.CONTENT_CAPTURE_ENABLED, Settings.Secure.DEFAULT_INPUT_METHOD, Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, Settings.Secure.DEVICE_PAIRED, Settings.Secure.DIALER_DEFAULT_APPLICATION, Settings.Secure.DISABLED_PRINT_SERVICES, Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +111 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.inputmethod; import static android.content.Context.DEVICE_ID_DEFAULT; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; import static android.os.IServiceManager.DUMP_FLAG_PROTO; Loading Loading @@ -315,7 +316,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // All known input methods. final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>(); private final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); // Mapping from deviceId to the device-specific imeId for that device. @GuardedBy("ImfLock.class") private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>(); private final InputMethodSubtypeSwitchingController mSwitchingController; Loading @@ -339,6 +342,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private int mDisplayIdToShowIme = INVALID_DISPLAY; @GuardedBy("ImfLock.class") private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT; @Nullable private StatusBarManagerInternal mStatusBarManagerInternal; private boolean mShowOngoingImeSwitcherForPhones; @GuardedBy("ImfLock.class") Loading Loading @@ -2464,11 +2470,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @StartInputReason int startInputReason, int unverifiedTargetSdkVersion, @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { // If no method is currently selected, do nothing. final String selectedMethodId = getSelectedMethodIdLocked(); if (selectedMethodId == null) { return InputBindResult.NO_IME; } String selectedMethodId = getSelectedMethodIdLocked(); if (!mSystemReady) { // If the system is not yet ready, we shouldn't be running third Loading @@ -2493,8 +2495,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return InputBindResult.NOT_IME_TARGET_WINDOW; } final int csDisplayId = cs.mSelfReportedDisplayId; final int oldDisplayIdToShowIme = mDisplayIdToShowIme; mDisplayIdToShowIme = mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId); // Potentially override the selected input method if the new display belongs to a virtual // device with a custom IME. if (oldDisplayIdToShowIme != mDisplayIdToShowIme) { final String deviceMethodId = computeCurrentDeviceMethodIdLocked(selectedMethodId); if (deviceMethodId == null) { mVisibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true); } else if (!Objects.equals(deviceMethodId, selectedMethodId)) { setInputMethodLocked(deviceMethodId, NOT_A_SUBTYPE_ID, mDeviceIdToShowIme); selectedMethodId = deviceMethodId; } } if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) { hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, null /* resultReceiver */, Loading @@ -2502,6 +2517,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return InputBindResult.NO_IME; } // If no method is currently selected, do nothing. if (selectedMethodId == null) { return InputBindResult.NO_IME; } if (mCurClient != cs) { prepareClientSwitchLocked(cs); } Loading Loading @@ -2568,6 +2588,62 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mBindingController.bindCurrentMethod(); } /** * Update the current deviceId and return the relevant imeId for this device. * 1. If the device changes to virtual and its custom IME is not available, then disable IME. * 2. If the device changes to virtual with valid custom IME, then return the custom IME. If * the old device was default, then store the current imeId so it can be restored. * 3. If the device changes to default, restore the default device IME. * 4. Otherwise keep the current imeId. */ @GuardedBy("ImfLock.class") private String computeCurrentDeviceMethodIdLocked(String currentMethodId) { if (mVdmInternal == null) { mVdmInternal = LocalServices.getService(VirtualDeviceManagerInternal.class); } if (mVdmInternal == null || !android.companion.virtual.flags.Flags.vdmCustomIme()) { return currentMethodId; } final int oldDeviceId = mDeviceIdToShowIme; mDeviceIdToShowIme = mVdmInternal.getDeviceIdForDisplayId(mDisplayIdToShowIme); if (mDeviceIdToShowIme == oldDeviceId) { return currentMethodId; } if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) { final String defaultDeviceMethodId = mSettings.getSelectedDefaultDeviceInputMethod(); if (DEBUG) { Slog.v(TAG, "Restoring default device input method: " + defaultDeviceMethodId); } return defaultDeviceMethodId; } final String deviceMethodId = mVirtualDeviceMethodMap.get(mDeviceIdToShowIme, currentMethodId); if (Objects.equals(deviceMethodId, currentMethodId)) { return currentMethodId; } else if (!mMethodMap.containsKey(deviceMethodId)) { if (DEBUG) { Slog.v(TAG, "Disabling IME on virtual device with id " + mDeviceIdToShowIme + " because its custom input method is not available: " + deviceMethodId); } return null; } if (oldDeviceId == DEVICE_ID_DEFAULT) { if (DEBUG) { Slog.v(TAG, "Storing default device input method " + currentMethodId); } mSettings.putSelectedDefaultDeviceInputMethod(currentMethodId); } if (DEBUG) { Slog.v(TAG, "Switching current input method from " + currentMethodId + " to device-specific one " + deviceMethodId + " because the current display " + mDisplayIdToShowIme + " belongs to device with id " + mDeviceIdToShowIme); } return deviceMethodId; } @GuardedBy("ImfLock.class") void invalidateAutofillSessionLocked() { mAutofillController.invalidateAutofillSession(); Loading Loading @@ -3242,6 +3318,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") void setInputMethodLocked(String id, int subtypeId) { setInputMethodLocked(id, subtypeId, DEVICE_ID_DEFAULT); } @GuardedBy("ImfLock.class") void setInputMethodLocked(String id, int subtypeId, int deviceId) { InputMethodInfo info = mMethodMap.get(id); if (info == null) { throw getExceptionForUnknownImeId(id); Loading Loading @@ -3285,6 +3366,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } // Changing to a different IME. if (mDeviceIdToShowIme != DEVICE_ID_DEFAULT && deviceId == DEVICE_ID_DEFAULT) { // This change should only be applicable to the default device but the current input // method is a custom one specific to a virtual device. So only update the settings // entry used to restore the default device input method once we want to show the IME // back on the default device. mSettings.putSelectedDefaultDeviceInputMethod(id); return; } IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { curMethod.removeStylusHandwritingWindow(); Loading Loading @@ -5308,12 +5397,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub StringBuilder builder = new StringBuilder(); if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( builder, enabledInputMethodsList, id)) { if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) { // Disabled input method is currently selected, switch to another one. final String selId = mSettings.getSelectedInputMethod(); if (id.equals(selId) && !chooseNewDefaultIMELocked()) { Slog.i(TAG, "Can't find new IME, unsetting the current input method."); resetSelectedInputMethodAndSubtypeLocked(""); } } else if (id.equals(mSettings.getSelectedDefaultDeviceInputMethod())) { // Disabled default device IME while using a virtual device one, choose a // new default one but only update the settings. InputMethodInfo newDefaultIme = InputMethodInfoUtils.getMostApplicableDefaultIME( mSettings.getEnabledInputMethodListLocked()); mSettings.putSelectedDefaultDeviceInputMethod( newDefaultIme == null ? "" : newDefaultIme.getId()); } // Previous state was enabled. return true; } else { Loading Loading @@ -5652,9 +5751,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @Override public void setVirtualDeviceInputMethodForAllUsers(int deviceId, @Nullable String imeId) { // TODO(b/287269288): validate that id belongs to a valid virtual device instead. Preconditions.checkArgument(deviceId != Context.DEVICE_ID_DEFAULT, "DeviceId " + deviceId + " does not belong to a virtual device."); Preconditions.checkArgument(deviceId != DEVICE_ID_DEFAULT, TextUtils.formatSimple("DeviceId %d is not a virtual device id.", deviceId)); synchronized (ImfLock.class) { if (imeId == null) { mVirtualDeviceMethodMap.remove(deviceId); Loading
services/core/java/com/android/server/inputmethod/InputMethodUtils.java +25 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import com.android.server.textservices.TextServicesManagerInternal; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Predicate; Loading Loading @@ -241,6 +242,12 @@ final class InputMethodUtils { Slog.d(TAG, "--- Switch the current user from " + mCurrentUserId + " to " + userId); } mCurrentUserId = userId; String ime = getSelectedInputMethod(); String defaultDeviceIme = getSelectedDefaultDeviceInputMethod(); if (defaultDeviceIme != null && !Objects.equals(ime, defaultDeviceIme)) { putSelectedInputMethod(defaultDeviceIme); putSelectedDefaultDeviceInputMethod(null); } } private void putString(@NonNull String key, @Nullable String str) { Loading Loading @@ -636,6 +643,24 @@ final class InputMethodUtils { return imi; } @Nullable String getSelectedDefaultDeviceInputMethod() { final String imi = getString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null); if (DEBUG) { Slog.d(TAG, "getSelectedDefaultDeviceInputMethodStr: " + imi + ", " + mCurrentUserId); } return imi; } void putSelectedDefaultDeviceInputMethod(String imeId) { if (DEBUG) { Slog.d(TAG, "putSelectedDefaultDeviceInputMethodStr: " + imeId + ", " + mCurrentUserId); } putString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, imeId); } void putDefaultVoiceInputMethod(String imeId) { if (DEBUG) { Slog.d(TAG, "putDefaultVoiceInputMethodStr: " + imeId + ", " + mCurrentUserId); Loading