Merge "Do not merge. Fix a memory leak of a Binder in SpellCheckerService" into ics-mr0
This commit is contained in:
@@ -145,6 +145,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
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -25,4 +25,5 @@ oneway interface ISpellCheckerSession {
|
||||
void onGetSuggestionsMultiple(
|
||||
in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords);
|
||||
void onCancel();
|
||||
void onClose();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user