am c89704a7: merge from open-source master

Merge commit 'c89704a77f9c51ebd8c1cc6863e15ff402a56c86' into kraken

* commit 'c89704a77f9c51ebd8c1cc6863e15ff402a56c86':
  Fix Memory Leak When Switching Input Methods
This commit is contained in:
The Android Open Source Project
2010-03-29 11:03:33 -07:00
committed by Android Git Automerger
4 changed files with 62 additions and 21 deletions

View File

@@ -47,9 +47,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
private static final int DO_UPDATE_CURSOR = 95;
private static final int DO_APP_PRIVATE_COMMAND = 100;
private static final int DO_TOGGLE_SOFT_INPUT = 105;
final HandlerCaller mCaller;
final InputMethodSession mInputMethodSession;
private static final int DO_FINISH_SESSION = 110;
HandlerCaller mCaller;
InputMethodSession mInputMethodSession;
// NOTE: we should have a cache of these.
static class InputMethodEventCallbackWrapper implements InputMethodSession.EventCallback {
@@ -127,6 +128,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
mInputMethodSession.toggleSoftInput(msg.arg1, msg.arg2);
return;
}
case DO_FINISH_SESSION: {
mInputMethodSession = null;
return;
}
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
@@ -174,4 +179,8 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
public void toggleSoftInput(int showFlags, int hideFlags) {
mCaller.executeOrSendMessage(mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags));
}
public void finishSession() {
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION));
}
}

View File

@@ -39,6 +39,7 @@ import android.view.inputmethod.InputMethodSession;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -64,9 +65,9 @@ class IInputMethodWrapper extends IInputMethod.Stub
private static final int DO_SHOW_SOFT_INPUT = 60;
private static final int DO_HIDE_SOFT_INPUT = 70;
final AbstractInputMethodService mTarget;
final WeakReference<AbstractInputMethodService> mTarget;
final HandlerCaller mCaller;
final InputMethod mInputMethod;
final WeakReference<InputMethod> mInputMethod;
static class Notifier {
boolean notified;
@@ -96,21 +97,32 @@ class IInputMethodWrapper extends IInputMethod.Stub
public IInputMethodWrapper(AbstractInputMethodService context,
InputMethod inputMethod) {
mTarget = context;
mCaller = new HandlerCaller(context, this);
mInputMethod = inputMethod;
mTarget = new WeakReference<AbstractInputMethodService>(context);
mCaller = new HandlerCaller(context.getApplicationContext(), this);
mInputMethod = new WeakReference<InputMethod>(inputMethod);
}
public InputMethod getInternalInputMethod() {
return mInputMethod;
return mInputMethod.get();
}
public void executeMessage(Message msg) {
InputMethod inputMethod = mInputMethod.get();
// Need a valid reference to the inputMethod for everything except a dump.
if (inputMethod == null && msg.what != DO_DUMP) {
Log.w(TAG, "Input method reference was null, ignoring message: " + msg.what);
return;
}
switch (msg.what) {
case DO_DUMP: {
AbstractInputMethodService target = mTarget.get();
if (target == null) {
return;
}
HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
try {
mTarget.dump((FileDescriptor)args.arg1,
target.dump((FileDescriptor)args.arg1,
(PrintWriter)args.arg2, (String[])args.arg3);
} catch (RuntimeException e) {
((PrintWriter)args.arg2).println("Exception: " + e);
@@ -122,22 +134,22 @@ class IInputMethodWrapper extends IInputMethod.Stub
}
case DO_ATTACH_TOKEN: {
mInputMethod.attachToken((IBinder)msg.obj);
inputMethod.attachToken((IBinder)msg.obj);
return;
}
case DO_SET_INPUT_CONTEXT: {
mInputMethod.bindInput((InputBinding)msg.obj);
inputMethod.bindInput((InputBinding)msg.obj);
return;
}
case DO_UNSET_INPUT_CONTEXT:
mInputMethod.unbindInput();
inputMethod.unbindInput();
return;
case DO_START_INPUT: {
HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
IInputContext inputContext = (IInputContext)args.arg1;
InputConnection ic = inputContext != null
? new InputConnectionWrapper(inputContext) : null;
mInputMethod.startInput(ic, (EditorInfo)args.arg2);
inputMethod.startInput(ic, (EditorInfo)args.arg2);
return;
}
case DO_RESTART_INPUT: {
@@ -145,33 +157,37 @@ class IInputMethodWrapper extends IInputMethod.Stub
IInputContext inputContext = (IInputContext)args.arg1;
InputConnection ic = inputContext != null
? new InputConnectionWrapper(inputContext) : null;
mInputMethod.restartInput(ic, (EditorInfo)args.arg2);
inputMethod.restartInput(ic, (EditorInfo)args.arg2);
return;
}
case DO_CREATE_SESSION: {
mInputMethod.createSession(new InputMethodSessionCallbackWrapper(
inputMethod.createSession(new InputMethodSessionCallbackWrapper(
mCaller.mContext, (IInputMethodCallback)msg.obj));
return;
}
case DO_SET_SESSION_ENABLED:
mInputMethod.setSessionEnabled((InputMethodSession)msg.obj,
inputMethod.setSessionEnabled((InputMethodSession)msg.obj,
msg.arg1 != 0);
return;
case DO_REVOKE_SESSION:
mInputMethod.revokeSession((InputMethodSession)msg.obj);
inputMethod.revokeSession((InputMethodSession)msg.obj);
return;
case DO_SHOW_SOFT_INPUT:
mInputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj);
inputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj);
return;
case DO_HIDE_SOFT_INPUT:
mInputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj);
inputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj);
return;
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
@Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
if (mTarget.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
AbstractInputMethodService target = mTarget.get();
if (target == null) {
return;
}
if (target.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
fout.println("Permission Denial: can't dump InputMethodManager from from pid="

View File

@@ -48,4 +48,6 @@ oneway interface IInputMethodSession {
void appPrivateCommand(String action, in Bundle data);
void toggleSoftInput(int showFlags, int hideFlags);
void finishSession();
}

View File

@@ -889,13 +889,27 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
}
}
private void finishSession(SessionState sessionState) {
if (sessionState != null && sessionState.session != null) {
try {
sessionState.session.finishSession();
} catch (RemoteException e) {
Log.w(TAG, "Session failed to close due to remote exception", e);
}
}
}
void clearCurMethodLocked() {
if (mCurMethod != null) {
for (ClientState cs : mClients.values()) {
cs.sessionRequested = false;
finishSession(cs.curSession);
cs.curSession = null;
}
finishSession(mEnabledSession);
mEnabledSession = null;
mCurMethod = null;
}
mStatusBar.setIconVisibility(mInputMethodIcon, false);