diff options
author | satok <satok@google.com> | 2011-11-18 16:39:20 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-11-18 16:39:20 -0800 |
commit | e36657e5416dbc9c1b22cc73174a958fafdfd736 (patch) | |
tree | 7a8375aab8737c9a9aa8f4002b3928bf3f19b32d | |
parent | d4b22ab4889f9b1885bfc0dc45667c846a171a98 (diff) | |
parent | e30983e799407aa2c5801597616fa6581d41241f (diff) | |
download | frameworks_base-e36657e5416dbc9c1b22cc73174a958fafdfd736.zip frameworks_base-e36657e5416dbc9c1b22cc73174a958fafdfd736.tar.gz frameworks_base-e36657e5416dbc9c1b22cc73174a958fafdfd736.tar.bz2 |
Merge "Do not merge. Fix a memory leak of a Binder in SpellCheckerService" into ics-mr0
4 files changed, 56 insertions, 7 deletions
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java index 2ecf307..1ad851d 100644 --- a/core/java/android/service/textservice/SpellCheckerService.java +++ b/core/java/android/service/textservice/SpellCheckerService.java @@ -146,6 +146,15 @@ public abstract class SpellCheckerService extends Service { public void onCancel() {} /** + * @hide + * Request to close this session. + * This function will run on the incoming IPC thread. + * So, this is not called on the main thread, + * but will be called in series on another thread. + */ + public void onClose() {} + + /** * @return Locale for this session */ public String getLocale() { @@ -162,7 +171,7 @@ public abstract class SpellCheckerService extends Service { // Preventing from exposing ISpellCheckerSession.aidl, create an internal class. private static class InternalISpellCheckerSession extends ISpellCheckerSession.Stub { - private final ISpellCheckerSessionListener mListener; + private ISpellCheckerSessionListener mListener; private final Session mSession; private final String mLocale; private final Bundle mBundle; @@ -192,6 +201,12 @@ public abstract class SpellCheckerService extends Service { mSession.onCancel(); } + @Override + public void onClose() { + mSession.onClose(); + mListener = null; + } + public String getLocale() { return mLocale; } diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java index 793f514..a80f4a3 100644 --- a/core/java/android/view/textservice/SpellCheckerSession.java +++ b/core/java/android/view/textservice/SpellCheckerSession.java @@ -152,6 +152,7 @@ public class SpellCheckerSession { public void close() { mIsUsed = false; try { + mSpellCheckerSessionListenerImpl.close(); mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl); } catch (RemoteException e) { // do nothing @@ -190,9 +191,10 @@ public class SpellCheckerSession { private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub { private static final int TASK_CANCEL = 1; private static final int TASK_GET_SUGGESTIONS_MULTIPLE = 2; + private static final int TASK_CLOSE = 3; private final Queue<SpellCheckerParams> mPendingTasks = new LinkedList<SpellCheckerParams>(); - private final Handler mHandler; + private Handler mHandler; private boolean mOpened; private ISpellCheckerSession mISpellCheckerSession; @@ -224,6 +226,9 @@ public class SpellCheckerSession { case TASK_GET_SUGGESTIONS_MULTIPLE: processGetSuggestionsMultiple(scp); break; + case TASK_CLOSE: + processClose(); + break; } } @@ -247,6 +252,13 @@ public class SpellCheckerSession { suggestionsLimit, sequentialWords)); } + public void close() { + if (DBG) { + Log.w(TAG, "close"); + } + processOrEnqueueTask(new SpellCheckerParams(TASK_CLOSE, null, 0, false)); + } + public boolean isDisconnected() { return mOpened && mISpellCheckerSession == null; } @@ -284,6 +296,22 @@ public class SpellCheckerSession { } } + private void processClose() { + if (!checkOpenConnection()) { + return; + } + if (DBG) { + Log.w(TAG, "Close spell checker tasks."); + } + try { + mISpellCheckerSession.onClose(); + mISpellCheckerSession = null; + mHandler = null; + } catch (RemoteException e) { + Log.e(TAG, "Failed to close " + e); + } + } + private void processGetSuggestionsMultiple(SpellCheckerParams scp) { if (!checkOpenConnection()) { return; diff --git a/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl index 5a00603..3c61968 100644 --- a/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl +++ b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl @@ -25,4 +25,5 @@ oneway interface ISpellCheckerSession { void onGetSuggestionsMultiple( in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords); void onCancel(); + void onClose(); } diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index 1976eba..373b11c 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -334,7 +334,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } final String sciId = info.getId(); final InternalServiceConnection connection = new InternalServiceConnection( - sciId, locale, scListener, bundle); + sciId, locale, bundle); final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); serviceIntent.setComponent(info.getComponent()); if (DBG) { @@ -635,7 +635,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (DBG) { Slog.w(TAG, "Remove " + removeList.get(i)); } - mListeners.remove(removeList.get(i)); + final InternalDeathRecipient idr = removeList.get(i); + idr.mScListener.asBinder().unlinkToDeath(idr, 0); + mListeners.remove(idr); } cleanLocked(); } @@ -664,6 +666,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { public void removeAll() { Slog.e(TAG, "Remove the spell checker bind unexpectedly."); synchronized(mSpellCheckerMap) { + final int size = mListeners.size(); + for (int i = 0; i < size; ++i) { + final InternalDeathRecipient idr = mListeners.get(i); + idr.mScListener.asBinder().unlinkToDeath(idr, 0); + } mListeners.clear(); cleanLocked(); } @@ -671,15 +678,13 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } private class InternalServiceConnection implements ServiceConnection { - private final ISpellCheckerSessionListener mListener; private final String mSciId; private final String mLocale; private final Bundle mBundle; public InternalServiceConnection( - String id, String locale, ISpellCheckerSessionListener listener, Bundle bundle) { + String id, String locale, Bundle bundle) { mSciId = id; mLocale = locale; - mListener = listener; mBundle = bundle; } |