Re-work IMM#getShortcutInputMethodsAndSubtypes()
It seems that InputMethodManager#getShortcutInputMethodsAndSubtypes()
was designed to be a bit more generalized concept, but in reality it
just ended up being a convenient API that returns a single Voice IME
subtype if exists. As far as we can tell, It has never returned two
or mode pairs. It also has never returned non-voice
InputMethodSubtype.
In order to support per-profile IME mode in InputMethodManagerService
without introducing a bunch of new complexity and technical debt, this
CL re-implements IMM#getShortcutInputMethodsAndSubtypes() based on how
it has been used actually in the ecosystem.
The first thing this CL changes is that
IMM#getShortcutInputMethodsAndSubtypes() no longer takes subtype
locale into account when looking for the best voice IME subtype. This
is because InputMethodSubtype is no longer a recommended way to
represent IME languages. Ignoring subtype locale makes the
implementation much easier to understand and maintain.
The second thing this CL changes is that
IMM#getShortcutInputMethodsAndSubtypes() is now just a utility method
that is implemented in the client side on top of other well-defined
public APIs such as IMM#getEnabledInputMethodList() and
IMM#getEnabledInputMethodSubtypeList(). This means that this API
becomes per-profile IME ready for free once other public APIs become
per-profile IME ready.
[1]: Ibd0f7ef5101013569c303820a3adc9038a97356d
4e4569dab5
Bug: 120709962
Test: AOSP Keyboard still shows voice IME shortcut when the device has
one or more IMEs that expose voice InputMethodSubtype.
Change-Id: Iaf31e9f3213f4e644b64c9658f1b59d371e3c2b4
This commit is contained in:
@@ -76,9 +76,9 @@ import com.android.internal.view.InputBindResult;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -232,6 +232,13 @@ public final class InputMethodManager {
|
||||
|
||||
static final String PENDING_EVENT_COUNTER = "aq:imm";
|
||||
|
||||
/**
|
||||
* A constant that represents Voice IME.
|
||||
*
|
||||
* @see InputMethodSubtype#getMode()
|
||||
*/
|
||||
private static final String SUBTYPE_MODE_VOICE = "voice";
|
||||
|
||||
/**
|
||||
* Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
|
||||
* or indirectly relied on {@link #sInstance} via reflection or something like that.
|
||||
@@ -2459,34 +2466,25 @@ public final class InputMethodManager {
|
||||
* Returns a map of all shortcut input method info and their subtypes.
|
||||
*/
|
||||
public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
|
||||
synchronized (mH) {
|
||||
HashMap<InputMethodInfo, List<InputMethodSubtype>> ret = new HashMap<>();
|
||||
try {
|
||||
// TODO: We should change the return type from List<Object> to List<Parcelable>
|
||||
List<Object> info = mService.getShortcutInputMethodsAndSubtypes();
|
||||
// "info" has imi1, subtype1, subtype2, imi2, subtype2, imi3, subtype3..in the list
|
||||
ArrayList<InputMethodSubtype> subtypes = null;
|
||||
if (info != null && !info.isEmpty()) {
|
||||
final int N = info.size();
|
||||
for (int i = 0; i < N; ++i) {
|
||||
Object o = info.get(i);
|
||||
if (o instanceof InputMethodInfo) {
|
||||
if (ret.containsKey(o)) {
|
||||
Log.e(TAG, "IMI list already contains the same InputMethod.");
|
||||
break;
|
||||
}
|
||||
subtypes = new ArrayList<>();
|
||||
ret.put((InputMethodInfo)o, subtypes);
|
||||
} else if (subtypes != null && o instanceof InputMethodSubtype) {
|
||||
subtypes.add((InputMethodSubtype)o);
|
||||
}
|
||||
}
|
||||
final List<InputMethodInfo> enabledImes = getEnabledInputMethodList();
|
||||
|
||||
// Ensure we check system IMEs first.
|
||||
enabledImes.sort(Comparator.comparingInt(imi -> imi.isSystem() ? 0 : 1));
|
||||
|
||||
final int numEnabledImes = enabledImes.size();
|
||||
for (int imiIndex = 0; imiIndex < numEnabledImes; ++imiIndex) {
|
||||
final InputMethodInfo imi = enabledImes.get(imiIndex);
|
||||
final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(
|
||||
imi, true);
|
||||
final int subtypeCount = subtypes.size();
|
||||
for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
|
||||
final InputMethodSubtype subtype = imi.getSubtypeAt(subtypeIndex);
|
||||
if (SUBTYPE_MODE_VOICE.equals(subtype.getMode())) {
|
||||
return Collections.singletonMap(imi, Collections.singletonList(subtype));
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,9 +42,6 @@ interface IInputMethodManager {
|
||||
List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
|
||||
boolean allowsImplicitlySelectedSubtypes);
|
||||
InputMethodSubtype getLastInputMethodSubtype();
|
||||
// TODO: We should change the return type from List to List<Parcelable>
|
||||
// Currently there is a bug that aidl doesn't accept List<Parcelable>
|
||||
List getShortcutInputMethodsAndSubtypes();
|
||||
|
||||
boolean showSoftInput(in IInputMethodClient client, int flags,
|
||||
in ResultReceiver resultReceiver);
|
||||
|
||||
Reference in New Issue
Block a user