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

Commit df5659d3 authored by satok's avatar satok
Browse files

Fix issues in TextServicesManagerService

Change-Id: I48c81226d824e8aad42e01e87fcf9a5b466d2321
parent 6be6d754
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -32,5 +32,6 @@ interface ITextServicesManager {
            in ITextServicesSessionListener tsListener,
            in ITextServicesSessionListener tsListener,
            in ISpellCheckerSessionListener scListener);
            in ISpellCheckerSessionListener scListener);
    oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
    oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
    oneway void setCurrentSpellChecker(in SpellCheckerInfo info);
    SpellCheckerInfo[] getEnabledSpellCheckers();
    SpellCheckerInfo[] getEnabledSpellCheckers();
}
}
+78 −32
Original line number Original line Diff line number Diff line
@@ -73,6 +73,16 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        synchronized (mSpellCheckerMap) {
        synchronized (mSpellCheckerMap) {
            buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
            buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
        }
        }
        SpellCheckerInfo sci = getCurrentSpellChecker(null);
        if (sci == null) {
            sci = findAvailSpellCheckerLocked(null, null);
            if (sci != null) {
                // Set the current spell checker if there is one or more spell checkers
                // available. In this case, "sci" is the first one in the available spell
                // checkers.
                setCurrentSpellCheckerLocked(sci);
            }
        }
    }
    }


    private class TextServicesMonitor extends PackageMonitor {
    private class TextServicesMonitor extends PackageMonitor {
@@ -87,10 +97,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                final int change = isPackageDisappearing(packageName);
                final int change = isPackageDisappearing(packageName);
                if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
                if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
                    // Package disappearing
                    // Package disappearing
                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
                    setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
                } else if (isPackageModified(packageName)) {
                } else if (isPackageModified(packageName)) {
                    // Package modified
                    // Package modified
                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
                    setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
                }
                }
            }
            }
        }
        }
@@ -160,13 +170,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
                Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
            }
            }
            if (TextUtils.isEmpty(curSpellCheckerId)) {
            if (TextUtils.isEmpty(curSpellCheckerId)) {
                final SpellCheckerInfo sci = findAvailSpellCheckerLocked(null, null);
                return null;
                if (sci == null) return null;
                // Set the current spell checker if there is one or more spell checkers
                // available. In this case, "sci" is the first one in the available spell
                // checkers.
                setCurrentSpellChecker(sci);
                return sci;
            }
            }
            return mSpellCheckerMap.get(curSpellCheckerId);
            return mSpellCheckerMap.get(curSpellCheckerId);
        }
        }
@@ -187,12 +191,13 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            if (!mSpellCheckerMap.containsKey(sciId)) {
            if (!mSpellCheckerMap.containsKey(sciId)) {
                return;
                return;
            }
            }
            final int uid = Binder.getCallingUid();
            if (mSpellCheckerBindGroups.containsKey(sciId)) {
            if (mSpellCheckerBindGroups.containsKey(sciId)) {
                final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
                final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
                if (bindGroup != null) {
                if (bindGroup != null) {
                    final InternalDeathRecipient recipient =
                    final InternalDeathRecipient recipient =
                            mSpellCheckerBindGroups.get(sciId).addListener(
                            mSpellCheckerBindGroups.get(sciId).addListener(
                                    tsListener, locale, scListener);
                                    tsListener, locale, scListener, uid);
                    if (recipient == null) {
                    if (recipient == null) {
                        if (DBG) {
                        if (DBG) {
                            Slog.w(TAG, "Didn't create a death recipient.");
                            Slog.w(TAG, "Didn't create a death recipient.");
@@ -204,14 +209,22 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                        bindGroup.removeAll();
                        bindGroup.removeAll();
                    } else if (bindGroup.mSpellChecker != null) {
                    } else if (bindGroup.mSpellChecker != null) {
                        if (DBG) {
                        if (DBG) {
                            Slog.w(TAG, "Existing bind found. Return a spell checker session now.");
                            Slog.w(TAG, "Existing bind found. Return a spell checker session now. "
                                    + "Listeners count = " + bindGroup.mListeners.size());
                        }
                        }
                        try {
                        try {
                            final ISpellCheckerSession session =
                            final ISpellCheckerSession session =
                                    bindGroup.mSpellChecker.getISpellCheckerSession(
                                    bindGroup.mSpellChecker.getISpellCheckerSession(
                                            recipient.mScLocale, recipient.mScListener);
                                            recipient.mScLocale, recipient.mScListener);
                            if (session != null) {
                                tsListener.onServiceConnected(session);
                                tsListener.onServiceConnected(session);
                                return;
                                return;
                            } else {
                                if (DBG) {
                                    Slog.w(TAG, "Existing bind already expired. ");
                                }
                                bindGroup.removeAll();
                            }
                        } catch (RemoteException e) {
                        } catch (RemoteException e) {
                            Slog.e(TAG, "Exception in getting spell checker session: " + e);
                            Slog.e(TAG, "Exception in getting spell checker session: " + e);
                            bindGroup.removeAll();
                            bindGroup.removeAll();
@@ -221,7 +234,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            }
            }
            final long ident = Binder.clearCallingIdentity();
            final long ident = Binder.clearCallingIdentity();
            try {
            try {
                startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener);
                startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener, uid);
            } finally {
            } finally {
                Binder.restoreCallingIdentity(ident);
                Binder.restoreCallingIdentity(ident);
            }
            }
@@ -230,7 +243,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
    }
    }


    private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
    private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) {
            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
            int uid) {
        if (DBG) {
            Slog.w(TAG, "Start spell checker session inner locked.");
        }
        final String sciId = info.getId();
        final String sciId = info.getId();
        final InternalServiceConnection connection = new InternalServiceConnection(
        final InternalServiceConnection connection = new InternalServiceConnection(
                sciId, locale, scListener);
                sciId, locale, scListener);
@@ -244,7 +261,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
            return;
            return;
        }
        }
        final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
        final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
                connection, tsListener, locale, scListener);
                connection, tsListener, locale, scListener, uid);
        mSpellCheckerBindGroups.put(sciId, group);
        mSpellCheckerBindGroups.put(sciId, group);
    }
    }


@@ -272,19 +289,39 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        }
        }
    }
    }


    private void setCurrentSpellChecker(SpellCheckerInfo sci) {
    @Override
    public void setCurrentSpellChecker(SpellCheckerInfo sci) {
        synchronized(mSpellCheckerMap) {
            if (mContext.checkCallingOrSelfPermission(
                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException(
                        "Requires permission "
                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
            }
            setCurrentSpellCheckerLocked(sci);
        }
    }

    private void setCurrentSpellCheckerLocked(SpellCheckerInfo sci) {
        if (DBG) {
        if (DBG) {
            Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
            Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
        }
        }
        if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
        if (sci == null || !mSpellCheckerMap.containsKey(sci.getId())) return;
        final long ident = Binder.clearCallingIdentity();
        try {
            Settings.Secure.putString(mContext.getContentResolver(),
            Settings.Secure.putString(mContext.getContentResolver(),
                    Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
                    Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    }


    // SpellCheckerBindGroup contains active text service session listeners.
    // SpellCheckerBindGroup contains active text service session listeners.
    // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
    // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
    // mSpellCheckerBindGroups
    // mSpellCheckerBindGroups
    private class SpellCheckerBindGroup {
    private class SpellCheckerBindGroup {
        private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
        private final InternalServiceConnection mInternalConnection;
        private final InternalServiceConnection mInternalConnection;
        private final ArrayList<InternalDeathRecipient> mListeners =
        private final ArrayList<InternalDeathRecipient> mListeners =
                new ArrayList<InternalDeathRecipient>();
                new ArrayList<InternalDeathRecipient>();
@@ -293,10 +330,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {


        public SpellCheckerBindGroup(InternalServiceConnection connection,
        public SpellCheckerBindGroup(InternalServiceConnection connection,
                ITextServicesSessionListener listener, String locale,
                ITextServicesSessionListener listener, String locale,
                ISpellCheckerSessionListener scListener) {
                ISpellCheckerSessionListener scListener, int uid) {
            mInternalConnection = connection;
            mInternalConnection = connection;
            mConnected = false;
            mConnected = false;
            addListener(listener, locale, scListener);
            addListener(listener, locale, scListener, uid);
        }
        }


        public void onServiceConnected(ISpellCheckerService spellChecker) {
        public void onServiceConnected(ISpellCheckerService spellChecker) {
@@ -310,7 +347,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                                listener.mScLocale, listener.mScListener);
                                listener.mScLocale, listener.mScListener);
                        listener.mTsListener.onServiceConnected(session);
                        listener.mTsListener.onServiceConnected(session);
                    } catch (RemoteException e) {
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Exception in getting spell checker session: " + e);
                        Slog.e(TAG, "Exception in getting the spell checker session: " + e);
                        removeAll();
                        removeAll();
                        return;
                        return;
                    }
                    }
@@ -321,7 +358,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        }
        }


        public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
        public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
                String locale, ISpellCheckerSessionListener scListener) {
                String locale, ISpellCheckerSessionListener scListener, int uid) {
            if (DBG) {
            if (DBG) {
                Slog.d(TAG, "addListener: " + locale);
                Slog.d(TAG, "addListener: " + locale);
            }
            }
@@ -336,10 +373,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                        }
                        }
                    }
                    }
                    recipient = new InternalDeathRecipient(
                    recipient = new InternalDeathRecipient(
                            this, tsListener, locale, scListener);
                            this, tsListener, locale, scListener, uid);
                    scListener.asBinder().linkToDeath(recipient, 0);
                    scListener.asBinder().linkToDeath(recipient, 0);
                    mListeners.add(new InternalDeathRecipient(
                    mListeners.add(recipient);
                            this, tsListener, locale, scListener));
                } catch(RemoteException e) {
                } catch(RemoteException e) {
                    // do nothing
                    // do nothing
                }
                }
@@ -350,7 +386,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {


        public void removeListener(ISpellCheckerSessionListener listener) {
        public void removeListener(ISpellCheckerSessionListener listener) {
            if (DBG) {
            if (DBG) {
                Slog.d(TAG, "remove listener");
                Slog.w(TAG, "remove listener: " + listener.hashCode());
            }
            }
            synchronized(mSpellCheckerMap) {
            synchronized(mSpellCheckerMap) {
                final int size = mListeners.size();
                final int size = mListeners.size();
@@ -359,11 +395,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                for (int i = 0; i < size; ++i) {
                for (int i = 0; i < size; ++i) {
                    final InternalDeathRecipient tempRecipient = mListeners.get(i);
                    final InternalDeathRecipient tempRecipient = mListeners.get(i);
                    if(tempRecipient.hasSpellCheckerListener(listener)) {
                    if(tempRecipient.hasSpellCheckerListener(listener)) {
                        if (DBG) {
                            Slog.w(TAG, "found existing listener.");
                        }
                        removeList.add(tempRecipient);
                        removeList.add(tempRecipient);
                    }
                    }
                }
                }
                final int removeSize = removeList.size();
                final int removeSize = removeList.size();
                for (int i = 0; i < removeSize; ++i) {
                for (int i = 0; i < removeSize; ++i) {
                    if (DBG) {
                        Slog.w(TAG, "Remove " + removeList.get(i));
                    }
                    mListeners.remove(removeList.get(i));
                    mListeners.remove(removeList.get(i));
                }
                }
                cleanLocked();
                cleanLocked();
@@ -385,10 +427,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {


        public void removeAll() {
        public void removeAll() {
            Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
            Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
            synchronized(mSpellCheckerMap) {
                mListeners.clear();
                mListeners.clear();
                cleanLocked();
                cleanLocked();
            }
            }
        }
        }
    }


    private class InternalServiceConnection implements ServiceConnection {
    private class InternalServiceConnection implements ServiceConnection {
        private final ISpellCheckerSessionListener mListener;
        private final ISpellCheckerSessionListener mListener;
@@ -426,17 +470,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
        public final ISpellCheckerSessionListener mScListener;
        public final ISpellCheckerSessionListener mScListener;
        public final String mScLocale;
        public final String mScLocale;
        private final SpellCheckerBindGroup mGroup;
        private final SpellCheckerBindGroup mGroup;
        public final int mUid;
        public InternalDeathRecipient(SpellCheckerBindGroup group,
        public InternalDeathRecipient(SpellCheckerBindGroup group,
                ITextServicesSessionListener tsListener, String scLocale,
                ITextServicesSessionListener tsListener, String scLocale,
                ISpellCheckerSessionListener scListener) {
                ISpellCheckerSessionListener scListener, int uid) {
            mTsListener = tsListener;
            mTsListener = tsListener;
            mScListener = scListener;
            mScListener = scListener;
            mScLocale = scLocale;
            mScLocale = scLocale;
            mGroup = group;
            mGroup = group;
            mUid = uid;
        }
        }


        public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
        public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
            return mScListener.equals(listener);
            return listener.asBinder().equals(mScListener.asBinder());
        }
        }


        @Override
        @Override