diff options
| author | 2012-02-10 02:22:57 -0800 | |
|---|---|---|
| committer | 2012-02-10 02:22:57 -0800 | |
| commit | 59d46b06653b5f55c2f26d3ff8d642ffda0cecd8 (patch) | |
| tree | bdd117467060579bace40958f00a5066bdaf6bff | |
| parent | 55ee84154b3afe07afef6311f707928856840f89 (diff) | |
| parent | 688bd47fccf1a1373e6287bc49b5b33fad12b7f3 (diff) | |
Merge "Add an api to switch to the next IME and subtype"
5 files changed, 159 insertions, 56 deletions
diff --git a/api/current.txt b/api/current.txt index 2037515e5632..bb05bfb087da 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24892,6 +24892,7 @@ package android.view.inputmethod { method public void showSoftInputFromInputMethod(android.os.IBinder, int); method public void showStatusIcon(android.os.IBinder, java.lang.String, int); method public boolean switchToLastInputMethod(android.os.IBinder); + method public boolean switchToNextInputMethod(android.os.IBinder, boolean); method public void toggleSoftInput(int, int); method public void toggleSoftInputFromWindow(android.os.IBinder, int, int); method public void updateCursor(android.view.View, int, int, int, int); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 0985e1465b0b..7171b58482d4 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -1593,6 +1593,27 @@ public final class InputMethodManager { } /** + * Force switch to the next input method and subtype. If there is no IME enabled except + * current IME and subtype, do nothing. + * @param imeToken Supplies the identifying token given to an input method when it was started, + * which allows it to perform this operation on itself. + * @param onlyCurrentIme if true, the framework will find the next subtype which + * belongs to the current IME + * @return true if the current input method and subtype was successfully switched to the next + * input method and subtype. + */ + public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) { + synchronized (mH) { + try { + return mService.switchToNextInputMethod(imeToken, onlyCurrentIme); + } catch (RemoteException e) { + Log.w(TAG, "IME died: " + mCurId, e); + return false; + } + } + } + + /** * Set additional input method subtypes. Only a process which shares the same uid with the IME * can add additional input method subtypes to the IME. * Please note that a subtype's status is stored in the system. diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 683aca542ba8..5d80b799df70 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -67,6 +67,7 @@ interface IInputMethodManager { InputMethodSubtype getCurrentInputMethodSubtype(); boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype); boolean switchToLastInputMethod(in IBinder token); + boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme); boolean setInputMethodEnabled(String id, boolean enabled); oneway void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes); } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index aba1bc627890..86669f8df6e0 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -101,6 +101,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -154,6 +155,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final IWindowManager mIWindowManager; final HandlerCaller mCaller; private final InputMethodFileManager mFileManager; + private final InputMethodAndSubtypeListManager mImListManager; final InputBindResult mNoBinding = new InputBindResult(null, null, -1); @@ -555,6 +557,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub synchronized (mMethodMap) { mFileManager = new InputMethodFileManager(mMethodMap); } + mImListManager = new InputMethodAndSubtypeListManager(context, this); (new MyPackageMonitor()).register(mContext, true); @@ -1693,6 +1696,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override + public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) { + synchronized (mMethodMap) { + final ImeSubtypeListItem nextSubtype = mImListManager.getNextInputMethod( + onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype); + if (nextSubtype == null) { + return false; + } + setInputMethodWithSubtypeId(token, nextSubtype.mImi.getId(), nextSubtype.mSubtypeId); + return true; + } + } + + @Override public InputMethodSubtype getLastInputMethodSubtype() { synchronized (mMethodMap) { final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked(); @@ -2109,62 +2125,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub hideInputMethodMenuLocked(); - final TreeMap<InputMethodInfo, List<InputMethodSubtype>> sortedImmis = - new TreeMap<InputMethodInfo, List<InputMethodSubtype>>( - new Comparator<InputMethodInfo>() { - @Override - public int compare(InputMethodInfo imi1, InputMethodInfo imi2) { - if (imi2 == null) return 0; - if (imi1 == null) return 1; - if (pm == null) { - return imi1.getId().compareTo(imi2.getId()); - } - CharSequence imiId1 = imi1.loadLabel(pm) + "/" + imi1.getId(); - CharSequence imiId2 = imi2.loadLabel(pm) + "/" + imi2.getId(); - return imiId1.toString().compareTo(imiId2.toString()); - } - }); - - sortedImmis.putAll(immis); - - final ArrayList<ImeSubtypeListItem> imList = new ArrayList<ImeSubtypeListItem>(); - - for (InputMethodInfo imi : sortedImmis.keySet()) { - if (imi == null) continue; - List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList = immis.get(imi); - HashSet<String> enabledSubtypeSet = new HashSet<String>(); - for (InputMethodSubtype subtype: explicitlyOrImplicitlyEnabledSubtypeList) { - enabledSubtypeSet.add(String.valueOf(subtype.hashCode())); - } - ArrayList<InputMethodSubtype> subtypes = getSubtypes(imi); - final CharSequence imeLabel = imi.loadLabel(pm); - if (showSubtypes && enabledSubtypeSet.size() > 0) { - final int subtypeCount = imi.getSubtypeCount(); - if (DEBUG) { - Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId()); - } - for (int j = 0; j < subtypeCount; ++j) { - final InputMethodSubtype subtype = imi.getSubtypeAt(j); - final String subtypeHashCode = String.valueOf(subtype.hashCode()); - // We show all enabled IMEs and subtypes when an IME is shown. - if (enabledSubtypeSet.contains(subtypeHashCode) - && ((mInputShown && !isScreenLocked) || !subtype.isAuxiliary())) { - final CharSequence subtypeLabel = - subtype.overridesImplicitlyEnabledSubtype() ? null - : subtype.getDisplayName(context, imi.getPackageName(), - imi.getServiceInfo().applicationInfo); - imList.add(new ImeSubtypeListItem(imeLabel, subtypeLabel, imi, j)); - - // Removing this subtype from enabledSubtypeSet because we no longer - // need to add an entry of this subtype to imList to avoid duplicated - // entries. - enabledSubtypeSet.remove(subtypeHashCode); - } - } - } else { - imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID)); - } - } + final List<ImeSubtypeListItem> imList = + mImListManager.getSortedInputMethodAndSubtypeList( + showSubtypes, mInputShown, isScreenLocked); if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtype(); @@ -2786,6 +2749,117 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + private static class InputMethodAndSubtypeListManager { + private final Context mContext; + private final PackageManager mPm; + private final InputMethodManagerService mImms; + public InputMethodAndSubtypeListManager(Context context, InputMethodManagerService imms) { + mContext = context; + mPm = context.getPackageManager(); + mImms = imms; + } + + private final TreeMap<InputMethodInfo, List<InputMethodSubtype>> mSortedImmis = + new TreeMap<InputMethodInfo, List<InputMethodSubtype>>( + new Comparator<InputMethodInfo>() { + @Override + public int compare(InputMethodInfo imi1, InputMethodInfo imi2) { + if (imi2 == null) return 0; + if (imi1 == null) return 1; + if (mPm == null) { + return imi1.getId().compareTo(imi2.getId()); + } + CharSequence imiId1 = imi1.loadLabel(mPm) + "/" + imi1.getId(); + CharSequence imiId2 = imi2.loadLabel(mPm) + "/" + imi2.getId(); + return imiId1.toString().compareTo(imiId2.toString()); + } + }); + + public ImeSubtypeListItem getNextInputMethod( + boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { + if (imi == null) { + return null; + } + final List<ImeSubtypeListItem> imList = getSortedInputMethodAndSubtypeList(); + if (imList.size() <= 1) { + return null; + } + final int N = imList.size(); + final int currentSubtypeId = subtype != null + ? mImms.getSubtypeIdFromHashCode(imi, subtype.hashCode()) + : NOT_A_SUBTYPE_ID; + for (int i = 0; i < N; ++i) { + final ImeSubtypeListItem isli = imList.get(i); + if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) { + if (!onlyCurrentIme) { + return imList.get((i + 1) % N); + } + for (int j = 0; j < N - 1; ++j) { + final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N); + if (candidate.mImi.equals(imi)) { + return candidate; + } + } + return null; + } + } + return null; + } + + public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList() { + return getSortedInputMethodAndSubtypeList(true, false, false); + } + + public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(boolean showSubtypes, + boolean inputShown, boolean isScreenLocked) { + final ArrayList<ImeSubtypeListItem> imList = new ArrayList<ImeSubtypeListItem>(); + final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis = + mImms.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(); + if (immis == null || immis.size() == 0) { + return Collections.emptyList(); + } + mSortedImmis.clear(); + mSortedImmis.putAll(immis); + for (InputMethodInfo imi : mSortedImmis.keySet()) { + if (imi == null) continue; + List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList = immis.get(imi); + HashSet<String> enabledSubtypeSet = new HashSet<String>(); + for (InputMethodSubtype subtype: explicitlyOrImplicitlyEnabledSubtypeList) { + enabledSubtypeSet.add(String.valueOf(subtype.hashCode())); + } + ArrayList<InputMethodSubtype> subtypes = getSubtypes(imi); + final CharSequence imeLabel = imi.loadLabel(mPm); + if (showSubtypes && enabledSubtypeSet.size() > 0) { + final int subtypeCount = imi.getSubtypeCount(); + if (DEBUG) { + Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId()); + } + for (int j = 0; j < subtypeCount; ++j) { + final InputMethodSubtype subtype = imi.getSubtypeAt(j); + final String subtypeHashCode = String.valueOf(subtype.hashCode()); + // We show all enabled IMEs and subtypes when an IME is shown. + if (enabledSubtypeSet.contains(subtypeHashCode) + && ((inputShown && !isScreenLocked) || !subtype.isAuxiliary())) { + final CharSequence subtypeLabel = + subtype.overridesImplicitlyEnabledSubtype() ? null + : subtype.getDisplayName(mContext, imi.getPackageName(), + imi.getServiceInfo().applicationInfo); + imList.add(new ImeSubtypeListItem(imeLabel, subtypeLabel, imi, j)); + + // Removing this subtype from enabledSubtypeSet because we no longer + // need to add an entry of this subtype to imList to avoid duplicated + // entries. + enabledSubtypeSet.remove(subtypeHashCode); + } + } + } else { + imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID)); + } + } + return imList; + } + } + /** * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java index db0694c8707d..6afdfbe31b05 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java @@ -197,6 +197,12 @@ public class BridgeIInputMethodManager implements IInputMethodManager { } @Override + public boolean switchToNextInputMethod(IBinder arg0, boolean arg1) throws RemoteException { + // TODO Auto-generated method stub + return false; + } + + @Override public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException { // TODO Auto-generated method stub |