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

Commit 2c8d5281 authored by Yohei Yukawa's avatar Yohei Yukawa Committed by Android (Google) Code Review
Browse files

Merge "Make sure to call back reportFinish() on the desired Handler." into nyc-dev

parents 0997bc8a 16e2c7b5
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -3287,7 +3287,6 @@ public final class ViewRootImpl implements ViewParent,
    private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
    private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
    private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
    private final static int MSG_FINISH_INPUT_CONNECTION = 12;
    private final static int MSG_CHECK_FOCUS = 13;
    private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
    private final static int MSG_DISPATCH_DRAG_EVENT = 15;
@@ -3327,8 +3326,6 @@ public final class ViewRootImpl implements ViewParent,
                    return "MSG_DISPATCH_GET_NEW_SURFACE";
                case MSG_DISPATCH_KEY_FROM_IME:
                    return "MSG_DISPATCH_KEY_FROM_IME";
                case MSG_FINISH_INPUT_CONNECTION:
                    return "MSG_FINISH_INPUT_CONNECTION";
                case MSG_CHECK_FOCUS:
                    return "MSG_CHECK_FOCUS";
                case MSG_CLOSE_SYSTEM_DIALOGS:
@@ -3549,12 +3546,6 @@ public final class ViewRootImpl implements ViewParent,
                }
                enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
            } break;
            case MSG_FINISH_INPUT_CONNECTION: {
                InputMethodManager imm = InputMethodManager.peekInstance();
                if (imm != null) {
                    imm.reportFinishInputConnection((InputConnection)msg.obj);
                }
            } break;
            case MSG_CHECK_FOCUS: {
                InputMethodManager imm = InputMethodManager.peekInstance();
                if (imm != null) {
@@ -5864,11 +5855,6 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    public void dispatchFinishInputConnection(InputConnection connection) {
        Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection);
        mHandler.sendMessage(msg);
    }

    public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
            Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
            Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+2 −2
Original line number Diff line number Diff line
@@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection {
     *
     * @hide
     */
    protected void reportFinish() {
        // Intentionaly empty
    public void reportFinish() {
        // Intentionally empty
    }

    /**
+12 −53
Original line number Diff line number Diff line
@@ -531,22 +531,25 @@ public final class InputMethodManager {

    private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
        private final InputMethodManager mParentInputMethodManager;
        private boolean mActive;

        public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
                final InputMethodManager inputMethodManager) {
            super(mainLooper, conn);
            mParentInputMethodManager = inputMethodManager;
            mActive = true;
        }

        @Override
        public boolean isActive() {
            return mParentInputMethodManager.mActive && mActive;
            return mParentInputMethodManager.mActive && !isFinished();
        }

        void deactivate() {
            mActive = false;
            if (isFinished()) {
                // This is a small performance optimization.  Still only the 1st call of
                // reportFinish() will take effect.
                return;
            }
            reportFinish();
        }

        @Override
@@ -563,7 +566,7 @@ public final class InputMethodManager {
        public String toString() {
            return "ControlledInputConnectionWrapper{"
                    + "connection=" + getInputConnection()
                    + " mActive=" + mActive
                    + " finished=" + isFinished()
                    + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
                    + "}";
        }
@@ -837,7 +840,6 @@ public final class InputMethodManager {
                    throw e.rethrowFromSystemServer();
                }
            }
            notifyInputConnectionFinished();
            mServedView = null;
            mCompletions = null;
            mServedConnecting = false;
@@ -845,48 +847,6 @@ public final class InputMethodManager {
        }
    }

    /**
     * Notifies the served view that the current InputConnection will no longer be used.
     */
    private void notifyInputConnectionFinished() {
        if (mServedView == null || mServedInputConnectionWrapper == null) {
            return;
        }
        final InputConnection inputConnection = mServedInputConnectionWrapper.getInputConnection();
        if (inputConnection == null) {
            return;
        }
        // We need to tell the previously served view that it is no
        // longer the input target, so it can reset its state.  Schedule
        // this call on its window's Handler so it will be on the correct
        // thread and outside of our lock.
        ViewRootImpl viewRootImpl = mServedView.getViewRootImpl();
        if (viewRootImpl != null) {
            // This will result in a call to reportFinishInputConnection() below.
            viewRootImpl.dispatchFinishInputConnection(inputConnection);
        }
    }

    /**
     * Called from the FINISH_INPUT_CONNECTION message above.
     * @hide
     */
    public void reportFinishInputConnection(InputConnection ic) {
        final InputConnection currentConnection;
        if (mServedInputConnectionWrapper == null) {
            currentConnection = null;
        } else {
            currentConnection = mServedInputConnectionWrapper.getInputConnection();
        }
        if (currentConnection != ic) {
            ic.finishComposingText();
            // To avoid modifying the public InputConnection interface
            if (ic instanceof BaseInputConnection) {
                ((BaseInputConnection) ic).reportFinish();
            }
        }
    }

    public void displayCompletions(View view, CompletionInfo[] completions) {
        checkFocus();
        synchronized (mH) {
@@ -1252,8 +1212,10 @@ public final class InputMethodManager {
            // Hook 'em up and let 'er rip.
            mCurrentTextBoxAttribute = tba;
            mServedConnecting = false;
            // Notify the served view that its previous input connection is finished
            notifyInputConnectionFinished();
            if (mServedInputConnectionWrapper != null) {
                mServedInputConnectionWrapper.deactivate();
                mServedInputConnectionWrapper = null;
            }
            ControlledInputConnectionWrapper servedContext;
            final int missingMethodFlags;
            if (ic != null) {
@@ -1278,9 +1240,6 @@ public final class InputMethodManager {
                servedContext = null;
                missingMethodFlags = 0;
            }
            if (mServedInputConnectionWrapper != null) {
                mServedInputConnectionWrapper.deactivate();
            }
            mServedInputConnectionWrapper = servedContext;

            try {
+48 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.view;

import com.android.internal.annotations.GuardedBy;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -25,6 +27,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.ExtractedTextRequest;
@@ -58,12 +61,16 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
    private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
    private static final int DO_CLEAR_META_KEY_STATES = 130;
    private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
    private static final int DO_REPORT_FINISH = 150;

    @NonNull
    private final WeakReference<InputConnection> mInputConnection;

    private Looper mMainLooper;
    private Handler mH;
    private Object mLock = new Object();
    @GuardedBy("mLock")
    private boolean mFinished = false;

    static class SomeArgs {
        Object arg1;
@@ -94,6 +101,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
        return mInputConnection.get();
    }

    protected boolean isFinished() {
        synchronized (mLock) {
            return mFinished;
        }
    }

    abstract protected boolean isActive();

    /**
@@ -206,6 +219,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
                seq, callback));
    }

    public void reportFinish() {
        dispatchMessage(obtainMessage(DO_REPORT_FINISH));
    }

    void dispatchMessage(Message msg) {
        // If we are calling this from the main thread, then we can call
        // right through.  Otherwise, we need to send the message to the
@@ -481,6 +498,36 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
                }
                return;
            }
            case DO_REPORT_FINISH: {
                // Note that we do not need to worry about race condition here, because 1) mFinished
                // is updated only inside this block, and 2) the code here is running on a Handler
                // hence we assume multiple DO_REPORT_FINISH messages will not be handled at the
                // same time.
                if (isFinished()) {
                    return;
                }
                try {
                    InputConnection ic = mInputConnection.get();
                    // Note we do NOT check isActive() here, because this is safe
                    // for an IME to call at any time, and we need to allow it
                    // through to clean up our state after the IME has switched to
                    // another client.
                    if (ic == null) {
                        return;
                    }
                    ic.finishComposingText();
                    // TODO: Make reportFinish() public method of InputConnection to remove this
                    // check.
                    if (ic instanceof BaseInputConnection) {
                        ((BaseInputConnection) ic).reportFinish();
                    }
                } finally {
                    synchronized (mLock) {
                        mFinished = true;
                    }
                }
                return;
            }
        }
        Log.w(TAG, "Unhandled message code: " + msg.what);
    }
+4 −1
Original line number Diff line number Diff line
@@ -83,8 +83,11 @@ public class EditableInputConnection extends BaseInputConnection {
        return false;
    }

    /**
     * @hide
     */
    @Override
    protected void reportFinish() {
    public void reportFinish() {
        super.reportFinish();

        synchronized(this) {