Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 119323a5 authored by satok's avatar satok Committed by Android Git Automerger
Browse files

am 59d46b06: Merge "Add an api to switch to the next IME and subtype"

* commit '59d46b06':
  Add an api to switch to the next IME and subtype
parents 6908dd71 59d46b06
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+21 −0
Original line number Diff line number Diff line
@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -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);
}
+130 −56
Original line number Diff line number Diff line
@@ -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);

@@ -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) {
@@ -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.
+6 −0
Original line number Diff line number Diff line
@@ -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