Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -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); core/java/android/view/inputmethod/InputMethodManager.java +21 −0 Original line number Diff line number Diff line Loading @@ -1592,6 +1592,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. Loading core/java/com/android/internal/view/IInputMethodManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); } services/java/com/android/server/InputMethodManagerService.java +130 −56 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -1692,6 +1695,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) { Loading Loading @@ -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(); Loading Loading @@ -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. Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,12 @@ public class BridgeIInputMethodManager implements IInputMethodManager { return false; } @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 Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -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);
core/java/android/view/inputmethod/InputMethodManager.java +21 −0 Original line number Diff line number Diff line Loading @@ -1592,6 +1592,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. Loading
core/java/com/android/internal/view/IInputMethodManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); }
services/java/com/android/server/InputMethodManagerService.java +130 −56 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -1692,6 +1695,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) { Loading Loading @@ -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(); Loading Loading @@ -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. Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,12 @@ public class BridgeIInputMethodManager implements IInputMethodManager { return false; } @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 Loading