diff options
| author | 2011-07-28 20:40:38 +0900 | |
|---|---|---|
| committer | 2011-07-29 09:57:07 +0900 | |
| commit | 6be6d7548fb7c29a4d46dc985318ab2adf69f95f (patch) | |
| tree | 5997d25d03c50eb01ec81955ce33ea76356a7fa3 | |
| parent | 2043b01b207aae3458da395bc6d501d76e59425c (diff) | |
Handle the existing binds to spell checkers correctly.
Change-Id: I32efce9f8c09b5a829b0431e8c444fc54b03b440
3 files changed, 107 insertions, 21 deletions
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java index 270f51208ce0..6f70ab831ea2 100644 --- a/core/java/android/service/textservice/SpellCheckerService.java +++ b/core/java/android/service/textservice/SpellCheckerService.java @@ -24,6 +24,7 @@ import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; +import android.util.Log; import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; @@ -36,6 +37,7 @@ import java.lang.ref.WeakReference; */ public abstract class SpellCheckerService extends Service { private static final String TAG = SpellCheckerService.class.getSimpleName(); + private static final boolean DBG = false; public static final String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService"; @@ -87,6 +89,9 @@ public abstract class SpellCheckerService extends Service { */ @Override public final IBinder onBind(final Intent intent) { + if (DBG) { + Log.w(TAG, "onBind"); + } return mBinder; } diff --git a/core/java/android/service/textservice/SpellCheckerSession.java b/core/java/android/service/textservice/SpellCheckerSession.java index 400454da40f9..0dff3a6d9ed2 100644 --- a/core/java/android/service/textservice/SpellCheckerSession.java +++ b/core/java/android/service/textservice/SpellCheckerSession.java @@ -30,7 +30,6 @@ import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import java.util.LinkedList; -import java.util.Locale; import java.util.Queue; /** @@ -125,6 +124,9 @@ public class SpellCheckerSession { */ public void getSuggestions( TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { + if (DBG) { + Log.w(TAG, "getSuggestions from " + mSpellCheckerInfo.getId()); + } // TODO: Handle multiple words suggestions by using WordBreakIterator mSpellCheckerSessionListenerImpl.getSuggestionsMultiple( textInfos, suggestionsLimit, sequentialWords); @@ -186,6 +188,9 @@ public class SpellCheckerSession { public void getSuggestionsMultiple( TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { + if (DBG) { + Log.w(TAG, "getSuggestionsMultiple"); + } processOrEnqueueTask( new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos, suggestionsLimit, sequentialWords)); @@ -204,6 +209,9 @@ public class SpellCheckerSession { } private void processOrEnqueueTask(SpellCheckerParams scp) { + if (DBG) { + Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession); + } if (mISpellCheckerSession == null) { mPendingTasks.offer(scp); } else { @@ -215,6 +223,9 @@ public class SpellCheckerSession { if (!checkOpenConnection()) { return; } + if (DBG) { + Log.w(TAG, "Cancel spell checker tasks."); + } try { mISpellCheckerSession.cancel(); } catch (RemoteException e) { @@ -226,6 +237,9 @@ public class SpellCheckerSession { if (!checkOpenConnection()) { return; } + if (DBG) { + Log.w(TAG, "Get suggestions from the spell checker."); + } try { mISpellCheckerSession.getSuggestionsMultiple( scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); @@ -254,6 +268,9 @@ public class SpellCheckerSession { private class InternalListener extends ITextServicesSessionListener.Stub { @Override public void onServiceConnected(ISpellCheckerSession session) { + if (DBG) { + Log.w(TAG, "SpellCheckerSession connected."); + } mSpellCheckerSessionListenerImpl.onServiceConnected(session); } } diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index 3e76a3a1ae4e..b2d9917ee1e8 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -30,6 +30,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; @@ -177,7 +178,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (!mSystemReady) { return; } - if (info == null || tsListener == null) { + if (info == null || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; } @@ -187,24 +188,66 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { return; } if (mSpellCheckerBindGroups.containsKey(sciId)) { - mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener); - return; + 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; + } + 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 InternalServiceConnection connection = new InternalServiceConnection( - sciId, locale, scListener); - final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); - serviceIntent.setComponent(info.getComponent()); - if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { - Slog.e(TAG, "Failed to get a spell checker service."); - return; + final long ident = Binder.clearCallingIdentity(); + try { + startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener); + } finally { + Binder.restoreCallingIdentity(ident); } - final SpellCheckerBindGroup group = new SpellCheckerBindGroup( - connection, tsListener, locale, scListener); - mSpellCheckerBindGroups.put(sciId, group); } return; } + private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale, + ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { + final String sciId = info.getId(); + final InternalServiceConnection connection = new InternalServiceConnection( + sciId, locale, scListener); + final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); + serviceIntent.setComponent(info.getComponent()); + if (DBG) { + Slog.w(TAG, "bind service: " + info.getId()); + } + if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { + Slog.e(TAG, "Failed to get a spell checker service."); + return; + } + final SpellCheckerBindGroup group = new SpellCheckerBindGroup( + connection, tsListener, locale, scListener); + mSpellCheckerBindGroups.put(sciId, group); + } + @Override public SpellCheckerInfo[] getEnabledSpellCheckers() { if (DBG) { @@ -242,14 +285,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from // mSpellCheckerBindGroups private class SpellCheckerBindGroup { - final InternalServiceConnection mInternalConnection; - final ArrayList<InternalDeathRecipient> mListeners = + private final InternalServiceConnection mInternalConnection; + private final ArrayList<InternalDeathRecipient> mListeners = new ArrayList<InternalDeathRecipient>(); + public ISpellCheckerService mSpellChecker; + public boolean mConnected; public SpellCheckerBindGroup(InternalServiceConnection connection, ITextServicesSessionListener listener, String locale, ISpellCheckerSessionListener scListener) { mInternalConnection = connection; + mConnected = false; addListener(listener, locale, scListener); } @@ -264,26 +310,32 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { listener.mScLocale, listener.mScListener); listener.mTsListener.onServiceConnected(session); } 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, - ISpellCheckerSessionListener scListener) { + public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener, + String locale, ISpellCheckerSessionListener scListener) { if (DBG) { Slog.d(TAG, "addListener: " + locale); } + InternalDeathRecipient recipient = null; synchronized(mSpellCheckerMap) { try { final int size = mListeners.size(); for (int i = 0; i < size; ++i) { if (mListeners.get(i).hasSpellCheckerListener(scListener)) { // 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); scListener.asBinder().linkToDeath(recipient, 0); mListeners.add(new InternalDeathRecipient( @@ -293,6 +345,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } cleanLocked(); } + return recipient; } public void removeListener(ISpellCheckerSessionListener listener) { @@ -322,11 +375,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.d(TAG, "cleanLocked"); } if (mListeners.isEmpty()) { - mSpellCheckerBindGroups.remove(this); + if (mSpellCheckerBindGroups.containsKey(this)) { + mSpellCheckerBindGroups.remove(this); + } // Unbind service when there is no active clients. mContext.unbindService(mInternalConnection); } } + + public void removeAll() { + Slog.e(TAG, "Remove the spell checker bind unexpectedly."); + mListeners.clear(); + cleanLocked(); + } } private class InternalServiceConnection implements ServiceConnection { @@ -343,6 +404,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized(mSpellCheckerMap) { + if (DBG) { + Slog.w(TAG, "onServiceConnected: " + name); + } ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); if (group != null) { |