Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f29c7d4d authored by The Android Open Source Project's avatar The Android Open Source Project Committed by Android Git Automerger
Browse files

am c89704a7: merge from open-source master

Merge commit 'c89704a7' into kraken

* commit 'c89704a7':
  Fix Memory Leak When Switching Input Methods
parents 7eeb9c23 c89704a7
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -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;
    private static final int DO_FINISH_SESSION = 110;

    final HandlerCaller mCaller;
    final InputMethodSession mInputMethodSession;
    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));
    }
}
+34 −18
Original line number Diff line number Diff line
@@ -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="
+2 −0
Original line number Diff line number Diff line
@@ -48,4 +48,6 @@ oneway interface IInputMethodSession {
    void appPrivateCommand(String action, in Bundle data);

    void toggleSoftInput(int showFlags, int hideFlags);

    void finishSession();
}
+14 −0
Original line number Diff line number Diff line
@@ -890,12 +890,26 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        }
    }
    
    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);