Skip to content

Commit e36657e

Browse files
satok16Android (Google) Code Review
authored andcommitted
Merge "Do not merge. Fix a memory leak of a Binder in SpellCheckerService" into ics-mr0
2 parents d4b22ab + e30983e commit e36657e

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

core/java/android/service/textservice/SpellCheckerService.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ public SuggestionsInfo[] onGetSuggestionsMultiple(TextInfo[] textInfos,
145145
*/
146146
public void onCancel() {}
147147

148+
/**
149+
* @hide
150+
* Request to close this session.
151+
* This function will run on the incoming IPC thread.
152+
* So, this is not called on the main thread,
153+
* but will be called in series on another thread.
154+
*/
155+
public void onClose() {}
156+
148157
/**
149158
* @return Locale for this session
150159
*/
@@ -162,7 +171,7 @@ public Bundle getBundle() {
162171

163172
// Preventing from exposing ISpellCheckerSession.aidl, create an internal class.
164173
private static class InternalISpellCheckerSession extends ISpellCheckerSession.Stub {
165-
private final ISpellCheckerSessionListener mListener;
174+
private ISpellCheckerSessionListener mListener;
166175
private final Session mSession;
167176
private final String mLocale;
168177
private final Bundle mBundle;
@@ -192,6 +201,12 @@ public void onCancel() {
192201
mSession.onCancel();
193202
}
194203

204+
@Override
205+
public void onClose() {
206+
mSession.onClose();
207+
mListener = null;
208+
}
209+
195210
public String getLocale() {
196211
return mLocale;
197212
}

core/java/android/view/textservice/SpellCheckerSession.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ public SpellCheckerInfo getSpellChecker() {
152152
public void close() {
153153
mIsUsed = false;
154154
try {
155+
mSpellCheckerSessionListenerImpl.close();
155156
mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl);
156157
} catch (RemoteException e) {
157158
// do nothing
@@ -190,9 +191,10 @@ private void handleOnGetSuggestionsMultiple(SuggestionsInfo[] suggestionInfos) {
190191
private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub {
191192
private static final int TASK_CANCEL = 1;
192193
private static final int TASK_GET_SUGGESTIONS_MULTIPLE = 2;
194+
private static final int TASK_CLOSE = 3;
193195
private final Queue<SpellCheckerParams> mPendingTasks =
194196
new LinkedList<SpellCheckerParams>();
195-
private final Handler mHandler;
197+
private Handler mHandler;
196198

197199
private boolean mOpened;
198200
private ISpellCheckerSession mISpellCheckerSession;
@@ -224,6 +226,9 @@ private void processTask(SpellCheckerParams scp) {
224226
case TASK_GET_SUGGESTIONS_MULTIPLE:
225227
processGetSuggestionsMultiple(scp);
226228
break;
229+
case TASK_CLOSE:
230+
processClose();
231+
break;
227232
}
228233
}
229234

@@ -247,6 +252,13 @@ public void getSuggestionsMultiple(
247252
suggestionsLimit, sequentialWords));
248253
}
249254

255+
public void close() {
256+
if (DBG) {
257+
Log.w(TAG, "close");
258+
}
259+
processOrEnqueueTask(new SpellCheckerParams(TASK_CLOSE, null, 0, false));
260+
}
261+
250262
public boolean isDisconnected() {
251263
return mOpened && mISpellCheckerSession == null;
252264
}
@@ -284,6 +296,22 @@ private void processCancel() {
284296
}
285297
}
286298

299+
private void processClose() {
300+
if (!checkOpenConnection()) {
301+
return;
302+
}
303+
if (DBG) {
304+
Log.w(TAG, "Close spell checker tasks.");
305+
}
306+
try {
307+
mISpellCheckerSession.onClose();
308+
mISpellCheckerSession = null;
309+
mHandler = null;
310+
} catch (RemoteException e) {
311+
Log.e(TAG, "Failed to close " + e);
312+
}
313+
}
314+
287315
private void processGetSuggestionsMultiple(SpellCheckerParams scp) {
288316
if (!checkOpenConnection()) {
289317
return;

core/java/com/android/internal/textservice/ISpellCheckerSession.aidl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ oneway interface ISpellCheckerSession {
2525
void onGetSuggestionsMultiple(
2626
in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords);
2727
void onCancel();
28+
void onClose();
2829
}

services/java/com/android/server/TextServicesManagerService.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String l
334334
}
335335
final String sciId = info.getId();
336336
final InternalServiceConnection connection = new InternalServiceConnection(
337-
sciId, locale, scListener, bundle);
337+
sciId, locale, bundle);
338338
final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
339339
serviceIntent.setComponent(info.getComponent());
340340
if (DBG) {
@@ -635,7 +635,9 @@ public void removeListener(ISpellCheckerSessionListener listener) {
635635
if (DBG) {
636636
Slog.w(TAG, "Remove " + removeList.get(i));
637637
}
638-
mListeners.remove(removeList.get(i));
638+
final InternalDeathRecipient idr = removeList.get(i);
639+
idr.mScListener.asBinder().unlinkToDeath(idr, 0);
640+
mListeners.remove(idr);
639641
}
640642
cleanLocked();
641643
}
@@ -664,22 +666,25 @@ private void cleanLocked() {
664666
public void removeAll() {
665667
Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
666668
synchronized(mSpellCheckerMap) {
669+
final int size = mListeners.size();
670+
for (int i = 0; i < size; ++i) {
671+
final InternalDeathRecipient idr = mListeners.get(i);
672+
idr.mScListener.asBinder().unlinkToDeath(idr, 0);
673+
}
667674
mListeners.clear();
668675
cleanLocked();
669676
}
670677
}
671678
}
672679

673680
private class InternalServiceConnection implements ServiceConnection {
674-
private final ISpellCheckerSessionListener mListener;
675681
private final String mSciId;
676682
private final String mLocale;
677683
private final Bundle mBundle;
678684
public InternalServiceConnection(
679-
String id, String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
685+
String id, String locale, Bundle bundle) {
680686
mSciId = id;
681687
mLocale = locale;
682-
mListener = listener;
683688
mBundle = bundle;
684689
}
685690

0 commit comments

Comments
 (0)