Loading core/java/android/service/textservice/SpellCheckerService.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.app.Service; import android.content.Intent; import android.content.Intent; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.view.textservice.SuggestionsInfo; import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import android.view.textservice.TextInfo; Loading @@ -36,6 +37,7 @@ import java.lang.ref.WeakReference; */ */ public abstract class SpellCheckerService extends Service { public abstract class SpellCheckerService extends Service { private static final String TAG = SpellCheckerService.class.getSimpleName(); private static final String TAG = SpellCheckerService.class.getSimpleName(); private static final boolean DBG = false; public static final String SERVICE_INTERFACE = public static final String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService"; "android.service.textservice.SpellCheckerService"; Loading Loading @@ -87,6 +89,9 @@ public abstract class SpellCheckerService extends Service { */ */ @Override @Override public final IBinder onBind(final Intent intent) { public final IBinder onBind(final Intent intent) { if (DBG) { Log.w(TAG, "onBind"); } return mBinder; return mBinder; } } Loading core/java/android/service/textservice/SpellCheckerSession.java +18 −1 Original line number Original line Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import android.view.textservice.TextInfo; import java.util.LinkedList; import java.util.LinkedList; import java.util.Locale; import java.util.Queue; import java.util.Queue; /** /** Loading Loading @@ -125,6 +124,9 @@ public class SpellCheckerSession { */ */ public void getSuggestions( public void getSuggestions( TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { if (DBG) { Log.w(TAG, "getSuggestions from " + mSpellCheckerInfo.getId()); } // TODO: Handle multiple words suggestions by using WordBreakIterator // TODO: Handle multiple words suggestions by using WordBreakIterator mSpellCheckerSessionListenerImpl.getSuggestionsMultiple( mSpellCheckerSessionListenerImpl.getSuggestionsMultiple( textInfos, suggestionsLimit, sequentialWords); textInfos, suggestionsLimit, sequentialWords); Loading Loading @@ -186,6 +188,9 @@ public class SpellCheckerSession { public void getSuggestionsMultiple( public void getSuggestionsMultiple( TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { if (DBG) { Log.w(TAG, "getSuggestionsMultiple"); } processOrEnqueueTask( processOrEnqueueTask( new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos, new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos, suggestionsLimit, sequentialWords)); suggestionsLimit, sequentialWords)); Loading @@ -204,6 +209,9 @@ public class SpellCheckerSession { } } private void processOrEnqueueTask(SpellCheckerParams scp) { private void processOrEnqueueTask(SpellCheckerParams scp) { if (DBG) { Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession); } if (mISpellCheckerSession == null) { if (mISpellCheckerSession == null) { mPendingTasks.offer(scp); mPendingTasks.offer(scp); } else { } else { Loading @@ -215,6 +223,9 @@ public class SpellCheckerSession { if (!checkOpenConnection()) { if (!checkOpenConnection()) { return; return; } } if (DBG) { Log.w(TAG, "Cancel spell checker tasks."); } try { try { mISpellCheckerSession.cancel(); mISpellCheckerSession.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -226,6 +237,9 @@ public class SpellCheckerSession { if (!checkOpenConnection()) { if (!checkOpenConnection()) { return; return; } } if (DBG) { Log.w(TAG, "Get suggestions from the spell checker."); } try { try { mISpellCheckerSession.getSuggestionsMultiple( mISpellCheckerSession.getSuggestionsMultiple( scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); Loading Loading @@ -254,6 +268,9 @@ public class SpellCheckerSession { private class InternalListener extends ITextServicesSessionListener.Stub { private class InternalListener extends ITextServicesSessionListener.Stub { @Override @Override public void onServiceConnected(ISpellCheckerSession session) { public void onServiceConnected(ISpellCheckerSession session) { if (DBG) { Log.w(TAG, "SpellCheckerSession connected."); } mSpellCheckerSessionListenerImpl.onServiceConnected(session); mSpellCheckerSessionListenerImpl.onServiceConnected(session); } } } } Loading services/java/com/android/server/TextServicesManagerService.java +84 −20 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo; import android.os.Binder; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteException; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemClock; Loading Loading @@ -177,7 +178,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (!mSystemReady) { if (!mSystemReady) { return; return; } } if (info == null || tsListener == null) { if (info == null || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; return; } } Loading @@ -187,13 +188,57 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { return; return; } } if (mSpellCheckerBindGroups.containsKey(sciId)) { if (mSpellCheckerBindGroups.containsKey(sciId)) { mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener); final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId); if (bindGroup != null) { final InternalDeathRecipient recipient = mSpellCheckerBindGroups.get(sciId).addListener( tsListener, locale, scListener); if (recipient == null) { if (DBG) { Slog.w(TAG, "Didn't create a death recipient."); } return; return; } } if (bindGroup.mSpellChecker == null & bindGroup.mConnected) { Slog.e(TAG, "The state of the spell checker bind group is illegal."); bindGroup.removeAll(); } else if (bindGroup.mSpellChecker != null) { if (DBG) { Slog.w(TAG, "Existing bind found. Return a spell checker session now."); } try { final ISpellCheckerSession session = bindGroup.mSpellChecker.getISpellCheckerSession( recipient.mScLocale, recipient.mScListener); tsListener.onServiceConnected(session); return; } catch (RemoteException e) { Slog.e(TAG, "Exception in getting spell checker session: " + e); bindGroup.removeAll(); } } } } final long ident = Binder.clearCallingIdentity(); try { startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener); } finally { Binder.restoreCallingIdentity(ident); } } return; } private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { final String sciId = info.getId(); final InternalServiceConnection connection = new InternalServiceConnection( final InternalServiceConnection connection = new InternalServiceConnection( sciId, locale, scListener); sciId, locale, scListener); final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); serviceIntent.setComponent(info.getComponent()); serviceIntent.setComponent(info.getComponent()); if (DBG) { Slog.w(TAG, "bind service: " + info.getId()); } if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { Slog.e(TAG, "Failed to get a spell checker service."); Slog.e(TAG, "Failed to get a spell checker service."); return; return; Loading @@ -202,8 +247,6 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { connection, tsListener, locale, scListener); connection, tsListener, locale, scListener); mSpellCheckerBindGroups.put(sciId, group); mSpellCheckerBindGroups.put(sciId, group); } } return; } @Override @Override public SpellCheckerInfo[] getEnabledSpellCheckers() { public SpellCheckerInfo[] getEnabledSpellCheckers() { Loading Loading @@ -242,14 +285,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // 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 { final InternalServiceConnection mInternalConnection; private final InternalServiceConnection mInternalConnection; final ArrayList<InternalDeathRecipient> mListeners = private final ArrayList<InternalDeathRecipient> mListeners = new ArrayList<InternalDeathRecipient>(); new ArrayList<InternalDeathRecipient>(); public ISpellCheckerService mSpellChecker; public boolean mConnected; public SpellCheckerBindGroup(InternalServiceConnection connection, public SpellCheckerBindGroup(InternalServiceConnection connection, ITextServicesSessionListener listener, String locale, ITextServicesSessionListener listener, String locale, ISpellCheckerSessionListener scListener) { ISpellCheckerSessionListener scListener) { mInternalConnection = connection; mInternalConnection = connection; mConnected = false; addListener(listener, locale, scListener); addListener(listener, locale, scListener); } } Loading @@ -264,26 +310,32 @@ 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); removeAll(); return; } } } } mSpellChecker = spellChecker; mConnected = true; } } } } public void addListener(ITextServicesSessionListener tsListener, String locale, public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { String locale, ISpellCheckerSessionListener scListener) { if (DBG) { if (DBG) { Slog.d(TAG, "addListener: " + locale); Slog.d(TAG, "addListener: " + locale); } } InternalDeathRecipient recipient = null; synchronized(mSpellCheckerMap) { synchronized(mSpellCheckerMap) { try { try { final int size = mListeners.size(); final int size = mListeners.size(); for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) { if (mListeners.get(i).hasSpellCheckerListener(scListener)) { if (mListeners.get(i).hasSpellCheckerListener(scListener)) { // do not add the lister if the group already contains this. // do not add the lister if the group already contains this. return; return null; } } } } final InternalDeathRecipient recipient = new InternalDeathRecipient( recipient = new InternalDeathRecipient( this, tsListener, locale, scListener); this, tsListener, locale, scListener); scListener.asBinder().linkToDeath(recipient, 0); scListener.asBinder().linkToDeath(recipient, 0); mListeners.add(new InternalDeathRecipient( mListeners.add(new InternalDeathRecipient( Loading @@ -293,6 +345,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } cleanLocked(); cleanLocked(); } } return recipient; } } public void removeListener(ISpellCheckerSessionListener listener) { public void removeListener(ISpellCheckerSessionListener listener) { Loading Loading @@ -322,11 +375,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.d(TAG, "cleanLocked"); Slog.d(TAG, "cleanLocked"); } } if (mListeners.isEmpty()) { if (mListeners.isEmpty()) { if (mSpellCheckerBindGroups.containsKey(this)) { mSpellCheckerBindGroups.remove(this); mSpellCheckerBindGroups.remove(this); } // Unbind service when there is no active clients. // Unbind service when there is no active clients. mContext.unbindService(mInternalConnection); mContext.unbindService(mInternalConnection); } } } } public void removeAll() { Slog.e(TAG, "Remove the spell checker bind unexpectedly."); mListeners.clear(); cleanLocked(); } } } private class InternalServiceConnection implements ServiceConnection { private class InternalServiceConnection implements ServiceConnection { Loading @@ -343,6 +404,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override @Override public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) { synchronized(mSpellCheckerMap) { synchronized(mSpellCheckerMap) { if (DBG) { Slog.w(TAG, "onServiceConnected: " + name); } ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); if (group != null) { if (group != null) { Loading Loading
core/java/android/service/textservice/SpellCheckerService.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.app.Service; import android.content.Intent; import android.content.Intent; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.view.textservice.SuggestionsInfo; import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import android.view.textservice.TextInfo; Loading @@ -36,6 +37,7 @@ import java.lang.ref.WeakReference; */ */ public abstract class SpellCheckerService extends Service { public abstract class SpellCheckerService extends Service { private static final String TAG = SpellCheckerService.class.getSimpleName(); private static final String TAG = SpellCheckerService.class.getSimpleName(); private static final boolean DBG = false; public static final String SERVICE_INTERFACE = public static final String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService"; "android.service.textservice.SpellCheckerService"; Loading Loading @@ -87,6 +89,9 @@ public abstract class SpellCheckerService extends Service { */ */ @Override @Override public final IBinder onBind(final Intent intent) { public final IBinder onBind(final Intent intent) { if (DBG) { Log.w(TAG, "onBind"); } return mBinder; return mBinder; } } Loading
core/java/android/service/textservice/SpellCheckerSession.java +18 −1 Original line number Original line Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import android.view.textservice.TextInfo; import java.util.LinkedList; import java.util.LinkedList; import java.util.Locale; import java.util.Queue; import java.util.Queue; /** /** Loading Loading @@ -125,6 +124,9 @@ public class SpellCheckerSession { */ */ public void getSuggestions( public void getSuggestions( TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { if (DBG) { Log.w(TAG, "getSuggestions from " + mSpellCheckerInfo.getId()); } // TODO: Handle multiple words suggestions by using WordBreakIterator // TODO: Handle multiple words suggestions by using WordBreakIterator mSpellCheckerSessionListenerImpl.getSuggestionsMultiple( mSpellCheckerSessionListenerImpl.getSuggestionsMultiple( textInfos, suggestionsLimit, sequentialWords); textInfos, suggestionsLimit, sequentialWords); Loading Loading @@ -186,6 +188,9 @@ public class SpellCheckerSession { public void getSuggestionsMultiple( public void getSuggestionsMultiple( TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { if (DBG) { Log.w(TAG, "getSuggestionsMultiple"); } processOrEnqueueTask( processOrEnqueueTask( new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos, new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos, suggestionsLimit, sequentialWords)); suggestionsLimit, sequentialWords)); Loading @@ -204,6 +209,9 @@ public class SpellCheckerSession { } } private void processOrEnqueueTask(SpellCheckerParams scp) { private void processOrEnqueueTask(SpellCheckerParams scp) { if (DBG) { Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession); } if (mISpellCheckerSession == null) { if (mISpellCheckerSession == null) { mPendingTasks.offer(scp); mPendingTasks.offer(scp); } else { } else { Loading @@ -215,6 +223,9 @@ public class SpellCheckerSession { if (!checkOpenConnection()) { if (!checkOpenConnection()) { return; return; } } if (DBG) { Log.w(TAG, "Cancel spell checker tasks."); } try { try { mISpellCheckerSession.cancel(); mISpellCheckerSession.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -226,6 +237,9 @@ public class SpellCheckerSession { if (!checkOpenConnection()) { if (!checkOpenConnection()) { return; return; } } if (DBG) { Log.w(TAG, "Get suggestions from the spell checker."); } try { try { mISpellCheckerSession.getSuggestionsMultiple( mISpellCheckerSession.getSuggestionsMultiple( scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); Loading Loading @@ -254,6 +268,9 @@ public class SpellCheckerSession { private class InternalListener extends ITextServicesSessionListener.Stub { private class InternalListener extends ITextServicesSessionListener.Stub { @Override @Override public void onServiceConnected(ISpellCheckerSession session) { public void onServiceConnected(ISpellCheckerSession session) { if (DBG) { Log.w(TAG, "SpellCheckerSession connected."); } mSpellCheckerSessionListenerImpl.onServiceConnected(session); mSpellCheckerSessionListenerImpl.onServiceConnected(session); } } } } Loading
services/java/com/android/server/TextServicesManagerService.java +84 −20 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo; import android.os.Binder; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteException; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemClock; Loading Loading @@ -177,7 +178,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (!mSystemReady) { if (!mSystemReady) { return; return; } } if (info == null || tsListener == null) { if (info == null || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; return; } } Loading @@ -187,13 +188,57 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { return; return; } } if (mSpellCheckerBindGroups.containsKey(sciId)) { if (mSpellCheckerBindGroups.containsKey(sciId)) { mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener); final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId); if (bindGroup != null) { final InternalDeathRecipient recipient = mSpellCheckerBindGroups.get(sciId).addListener( tsListener, locale, scListener); if (recipient == null) { if (DBG) { Slog.w(TAG, "Didn't create a death recipient."); } return; return; } } if (bindGroup.mSpellChecker == null & bindGroup.mConnected) { Slog.e(TAG, "The state of the spell checker bind group is illegal."); bindGroup.removeAll(); } else if (bindGroup.mSpellChecker != null) { if (DBG) { Slog.w(TAG, "Existing bind found. Return a spell checker session now."); } try { final ISpellCheckerSession session = bindGroup.mSpellChecker.getISpellCheckerSession( recipient.mScLocale, recipient.mScListener); tsListener.onServiceConnected(session); return; } catch (RemoteException e) { Slog.e(TAG, "Exception in getting spell checker session: " + e); bindGroup.removeAll(); } } } } final long ident = Binder.clearCallingIdentity(); try { startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener); } finally { Binder.restoreCallingIdentity(ident); } } return; } private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { final String sciId = info.getId(); final InternalServiceConnection connection = new InternalServiceConnection( final InternalServiceConnection connection = new InternalServiceConnection( sciId, locale, scListener); sciId, locale, scListener); final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); serviceIntent.setComponent(info.getComponent()); serviceIntent.setComponent(info.getComponent()); if (DBG) { Slog.w(TAG, "bind service: " + info.getId()); } if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { Slog.e(TAG, "Failed to get a spell checker service."); Slog.e(TAG, "Failed to get a spell checker service."); return; return; Loading @@ -202,8 +247,6 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { connection, tsListener, locale, scListener); connection, tsListener, locale, scListener); mSpellCheckerBindGroups.put(sciId, group); mSpellCheckerBindGroups.put(sciId, group); } } return; } @Override @Override public SpellCheckerInfo[] getEnabledSpellCheckers() { public SpellCheckerInfo[] getEnabledSpellCheckers() { Loading Loading @@ -242,14 +285,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // 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 { final InternalServiceConnection mInternalConnection; private final InternalServiceConnection mInternalConnection; final ArrayList<InternalDeathRecipient> mListeners = private final ArrayList<InternalDeathRecipient> mListeners = new ArrayList<InternalDeathRecipient>(); new ArrayList<InternalDeathRecipient>(); public ISpellCheckerService mSpellChecker; public boolean mConnected; public SpellCheckerBindGroup(InternalServiceConnection connection, public SpellCheckerBindGroup(InternalServiceConnection connection, ITextServicesSessionListener listener, String locale, ITextServicesSessionListener listener, String locale, ISpellCheckerSessionListener scListener) { ISpellCheckerSessionListener scListener) { mInternalConnection = connection; mInternalConnection = connection; mConnected = false; addListener(listener, locale, scListener); addListener(listener, locale, scListener); } } Loading @@ -264,26 +310,32 @@ 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); removeAll(); return; } } } } mSpellChecker = spellChecker; mConnected = true; } } } } public void addListener(ITextServicesSessionListener tsListener, String locale, public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { String locale, ISpellCheckerSessionListener scListener) { if (DBG) { if (DBG) { Slog.d(TAG, "addListener: " + locale); Slog.d(TAG, "addListener: " + locale); } } InternalDeathRecipient recipient = null; synchronized(mSpellCheckerMap) { synchronized(mSpellCheckerMap) { try { try { final int size = mListeners.size(); final int size = mListeners.size(); for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) { if (mListeners.get(i).hasSpellCheckerListener(scListener)) { if (mListeners.get(i).hasSpellCheckerListener(scListener)) { // do not add the lister if the group already contains this. // do not add the lister if the group already contains this. return; return null; } } } } final InternalDeathRecipient recipient = new InternalDeathRecipient( recipient = new InternalDeathRecipient( this, tsListener, locale, scListener); this, tsListener, locale, scListener); scListener.asBinder().linkToDeath(recipient, 0); scListener.asBinder().linkToDeath(recipient, 0); mListeners.add(new InternalDeathRecipient( mListeners.add(new InternalDeathRecipient( Loading @@ -293,6 +345,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } cleanLocked(); cleanLocked(); } } return recipient; } } public void removeListener(ISpellCheckerSessionListener listener) { public void removeListener(ISpellCheckerSessionListener listener) { Loading Loading @@ -322,11 +375,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.d(TAG, "cleanLocked"); Slog.d(TAG, "cleanLocked"); } } if (mListeners.isEmpty()) { if (mListeners.isEmpty()) { if (mSpellCheckerBindGroups.containsKey(this)) { mSpellCheckerBindGroups.remove(this); mSpellCheckerBindGroups.remove(this); } // Unbind service when there is no active clients. // Unbind service when there is no active clients. mContext.unbindService(mInternalConnection); mContext.unbindService(mInternalConnection); } } } } public void removeAll() { Slog.e(TAG, "Remove the spell checker bind unexpectedly."); mListeners.clear(); cleanLocked(); } } } private class InternalServiceConnection implements ServiceConnection { private class InternalServiceConnection implements ServiceConnection { Loading @@ -343,6 +404,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override @Override public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) { synchronized(mSpellCheckerMap) { synchronized(mSpellCheckerMap) { if (DBG) { Slog.w(TAG, "onServiceConnected: " + name); } ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); if (group != null) { if (group != null) { Loading