Search in sources :

Example 31 with InputBindResult

use of com.android.internal.view.InputBindResult in project android_frameworks_base by ResurrectionRemix.

the class InputMethodManager method startInputInner.

boolean startInputInner(@InputMethodClient.StartInputReason final int startInputReason, IBinder windowGainingFocus, int controlFlags, int softInputMode, int windowFlags) {
    final View view;
    synchronized (mH) {
        view = mServedView;
        // Make sure we have a window token for the served view.
        if (DEBUG) {
            Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) + " reason=" + InputMethodClient.getStartInputReason(startInputReason));
        }
        if (view == null) {
            if (DEBUG)
                Log.v(TAG, "ABORT input: no served view!");
            return false;
        }
    }
    // Now we need to get an input connection from the served view.
    // This is complicated in a couple ways: we can't be holding our lock
    // when calling out to the view, and we need to make sure we call into
    // the view on the same thread that is driving its view hierarchy.
    Handler vh = view.getHandler();
    if (vh == null) {
        // screen without a connection.
        if (DEBUG)
            Log.v(TAG, "ABORT input: no handler for view! Close current input.");
        closeCurrentInput();
        return false;
    }
    if (vh.getLooper() != Looper.myLooper()) {
        // we need to reschedule our work for over there.
        if (DEBUG)
            Log.v(TAG, "Starting input: reschedule to view thread");
        vh.post(new Runnable() {

            @Override
            public void run() {
                startInputInner(startInputReason, null, 0, 0, 0);
            }
        });
        return false;
    }
    // Okay we are now ready to call into the served view and have it
    // do its stuff.
    // Life is good: let's hook everything up!
    EditorInfo tba = new EditorInfo();
    // Note: Use Context#getOpPackageName() rather than Context#getPackageName() so that the
    // system can verify the consistency between the uid of this process and package name passed
    // from here. See comment of Context#getOpPackageName() for details.
    tba.packageName = view.getContext().getOpPackageName();
    tba.fieldId = view.getId();
    InputConnection ic = view.onCreateInputConnection(tba);
    if (DEBUG)
        Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
    synchronized (mH) {
        // changed.
        if (mServedView != view || !mServedConnecting) {
            // Something else happened, so abort.
            if (DEBUG)
                Log.v(TAG, "Starting input: finished by someone else. view=" + dumpViewInfo(view) + " mServedView=" + dumpViewInfo(mServedView) + " mServedConnecting=" + mServedConnecting);
            return false;
        }
        // connected so we want to restart it.
        if (mCurrentTextBoxAttribute == null) {
            controlFlags |= CONTROL_START_INITIAL;
        }
        // Hook 'em up and let 'er rip.
        mCurrentTextBoxAttribute = tba;
        mServedConnecting = false;
        if (mServedInputConnectionWrapper != null) {
            mServedInputConnectionWrapper.deactivate();
            mServedInputConnectionWrapper = null;
        }
        ControlledInputConnectionWrapper servedContext;
        final int missingMethodFlags;
        if (ic != null) {
            mCursorSelStart = tba.initialSelStart;
            mCursorSelEnd = tba.initialSelEnd;
            mCursorCandStart = -1;
            mCursorCandEnd = -1;
            mCursorRect.setEmpty();
            mCursorAnchorInfo = null;
            final Handler icHandler;
            missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
            if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER) != 0) {
                // InputConnection#getHandler() is not implemented.
                icHandler = null;
            } else {
                icHandler = ic.getHandler();
            }
            servedContext = new ControlledInputConnectionWrapper(icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this);
        } else {
            servedContext = null;
            missingMethodFlags = 0;
        }
        mServedInputConnectionWrapper = servedContext;
        try {
            if (DEBUG)
                Log.v(TAG, "START INPUT: view=" + dumpViewInfo(view) + " ic=" + ic + " tba=" + tba + " controlFlags=#" + Integer.toHexString(controlFlags));
            final InputBindResult res = mService.startInputOrWindowGainedFocus(startInputReason, mClient, windowGainingFocus, controlFlags, softInputMode, windowFlags, tba, servedContext, missingMethodFlags);
            if (DEBUG)
                Log.v(TAG, "Starting input: Bind result=" + res);
            if (res != null) {
                if (res.id != null) {
                    setInputChannelLocked(res.channel);
                    mBindSequence = res.sequence;
                    mCurMethod = res.method;
                    mCurId = res.id;
                    mNextUserActionNotificationSequenceNumber = res.userActionNotificationSequenceNumber;
                    if (mServedInputConnectionWrapper != null) {
                        mServedInputConnectionWrapper.setInputMethodId(mCurId);
                    }
                } else {
                    if (res.channel != null && res.channel != mCurChannel) {
                        res.channel.dispose();
                    }
                    if (mCurMethod == null) {
                        // This means there is no input method available.
                        if (DEBUG)
                            Log.v(TAG, "ABORT input: no input method!");
                        return true;
                    }
                }
            } else {
                if (startInputReason == InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN) {
                    // TODO: InputBindResult should have the error code.
                    if (DEBUG)
                        Log.w(TAG, "startInputOrWindowGainedFocus failed. " + "Window focus may have already been lost. " + "win=" + windowGainingFocus + " view=" + dumpViewInfo(view));
                    if (!mActive) {
                        // mHasBeenInactive is a latch switch to forcefully refresh IME focus
                        // state when an inactive (mActive == false) client is gaining window
                        // focus. In case we have unnecessary disable the latch due to this
                        // spurious wakeup, we re-enable the latch here.
                        // TODO: Come up with more robust solution.
                        mHasBeenInactive = true;
                    }
                }
            }
            if (mCurMethod != null && mCompletions != null) {
                try {
                    mCurMethod.displayCompletions(mCompletions);
                } catch (RemoteException e) {
                }
            }
        } catch (RemoteException e) {
            Log.w(TAG, "IME died: " + mCurId, e);
        }
    }
    return true;
}
Also used : InputBindResult(com.android.internal.view.InputBindResult) Handler(android.os.Handler) RemoteException(android.os.RemoteException) View(android.view.View)

Example 32 with InputBindResult

use of com.android.internal.view.InputBindResult in project android_frameworks_base by ResurrectionRemix.

the class InputMethodManagerService method onSessionCreated.

void onSessionCreated(IInputMethod method, IInputMethodSession session, InputChannel channel) {
    synchronized (mMethodMap) {
        if (mCurMethod != null && method != null && mCurMethod.asBinder() == method.asBinder()) {
            if (mCurClient != null) {
                clearClientSessionLocked(mCurClient);
                mCurClient.curSession = new SessionState(mCurClient, method, session, channel);
                InputBindResult res = attachNewInputLocked(true);
                if (res.method != null) {
                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(MSG_BIND_CLIENT, mCurClient.client, res));
                }
                return;
            }
        }
    }
    // Session abandoned.  Close its associated input channel.
    channel.dispose();
}
Also used : InputBindResult(com.android.internal.view.InputBindResult)

Example 33 with InputBindResult

use of com.android.internal.view.InputBindResult in project android_frameworks_base by ResurrectionRemix.

the class InputMethodManagerService method startInputInnerLocked.

InputBindResult startInputInnerLocked() {
    if (mCurMethodId == null) {
        return mNoBinding;
    }
    if (!mSystemReady) {
        // party code.
        return new InputBindResult(null, null, mCurMethodId, mCurSeq, mCurUserActionNotificationSequenceNumber);
    }
    InputMethodInfo info = mMethodMap.get(mCurMethodId);
    if (info == null) {
        throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
    }
    unbindCurrentMethodLocked(true);
    mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
    mCurIntent.setComponent(info.getComponent());
    mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, com.android.internal.R.string.input_method_binding_label);
    mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
    if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND | Context.BIND_SHOWING_UI)) {
        mLastBindTime = SystemClock.uptimeMillis();
        mHaveConnection = true;
        mCurId = info.getId();
        mCurToken = new Binder();
        try {
            if (true || DEBUG)
                Slog.v(TAG, "Adding window token: " + mCurToken);
            mIWindowManager.addWindowToken(mCurToken, WindowManager.LayoutParams.TYPE_INPUT_METHOD);
        } catch (RemoteException e) {
        }
        return new InputBindResult(null, null, mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
    } else {
        mCurIntent = null;
        Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent);
    }
    return null;
}
Also used : IBinder(android.os.IBinder) Binder(android.os.Binder) InputBindResult(com.android.internal.view.InputBindResult) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) RemoteException(android.os.RemoteException) InputMethodInfo(android.view.inputmethod.InputMethodInfo)

Example 34 with InputBindResult

use of com.android.internal.view.InputBindResult in project android_frameworks_base by ResurrectionRemix.

the class InputMethodManagerService method startInputUncheckedLocked.

InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext, /* @InputConnectionInspector.missingMethods */
final int missingMethods, @NonNull EditorInfo attribute, int controlFlags) {
    // If no method is currently selected, do nothing.
    if (mCurMethodId == null) {
        return mNoBinding;
    }
    if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid, attribute.packageName)) {
        Slog.e(TAG, "Rejecting this client as it reported an invalid package name." + " uid=" + cs.uid + " package=" + attribute.packageName);
        return mNoBinding;
    }
    if (mCurClient != cs) {
        // Was the keyguard locked when switching over to the new client?
        mCurClientInKeyguard = isKeyguardLocked();
        // If the client is changing, we need to switch over to the new
        // one.
        unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_SWITCH_CLIENT);
        if (DEBUG)
            Slog.v(TAG, "switching to client: client=" + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
        // If the screen is on, inform the new client it is active
        if (mIsInteractive) {
            executeOrSendMessage(cs.client, mCaller.obtainMessageIO(MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, cs));
        }
    }
    // Bump up the sequence for this client and attach it.
    mCurSeq++;
    if (mCurSeq <= 0)
        mCurSeq = 1;
    mCurClient = cs;
    mCurInputContext = inputContext;
    mCurInputContextMissingMethods = missingMethods;
    mCurAttribute = attribute;
    // Check if the input method is changing.
    if (mCurId != null && mCurId.equals(mCurMethodId)) {
        if (cs.curSession != null) {
            // then just return it.
            return attachNewInputLocked((controlFlags & InputMethodManager.CONTROL_START_INITIAL) != 0);
        }
        if (mHaveConnection) {
            if (mCurMethod != null) {
                // Return to client, and we will get back with it when
                // we have had a session made for it.
                requestClientSessionLocked(cs);
                return new InputBindResult(null, null, mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
            } else if (SystemClock.uptimeMillis() < (mLastBindTime + TIME_TO_RECONNECT)) {
                // to see if we can get back in touch with the service.
                return new InputBindResult(null, null, mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
            } else {
                EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId, SystemClock.uptimeMillis() - mLastBindTime, 0);
            }
        }
    }
    return startInputInnerLocked();
}
Also used : InputBindResult(com.android.internal.view.InputBindResult)

Example 35 with InputBindResult

use of com.android.internal.view.InputBindResult in project android_frameworks_base by crdroidandroid.

the class InputMethodManagerService method startInputUncheckedLocked.

InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext, /* @InputConnectionInspector.missingMethods */
final int missingMethods, @NonNull EditorInfo attribute, int controlFlags) {
    // If no method is currently selected, do nothing.
    if (mCurMethodId == null) {
        return mNoBinding;
    }
    if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid, attribute.packageName)) {
        Slog.e(TAG, "Rejecting this client as it reported an invalid package name." + " uid=" + cs.uid + " package=" + attribute.packageName);
        return mNoBinding;
    }
    if (mCurClient != cs) {
        // Was the keyguard locked when switching over to the new client?
        mCurClientInKeyguard = isKeyguardLocked();
        // If the client is changing, we need to switch over to the new
        // one.
        unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_SWITCH_CLIENT);
        if (DEBUG)
            Slog.v(TAG, "switching to client: client=" + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
        // If the screen is on, inform the new client it is active
        if (mIsInteractive) {
            executeOrSendMessage(cs.client, mCaller.obtainMessageIO(MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, cs));
        }
    }
    // Bump up the sequence for this client and attach it.
    mCurSeq++;
    if (mCurSeq <= 0)
        mCurSeq = 1;
    mCurClient = cs;
    mCurInputContext = inputContext;
    mCurInputContextMissingMethods = missingMethods;
    mCurAttribute = attribute;
    // Check if the input method is changing.
    if (mCurId != null && mCurId.equals(mCurMethodId)) {
        if (cs.curSession != null) {
            // then just return it.
            return attachNewInputLocked((controlFlags & InputMethodManager.CONTROL_START_INITIAL) != 0);
        }
        if (mHaveConnection) {
            if (mCurMethod != null) {
                // Return to client, and we will get back with it when
                // we have had a session made for it.
                requestClientSessionLocked(cs);
                return new InputBindResult(null, null, mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
            } else if (SystemClock.uptimeMillis() < (mLastBindTime + TIME_TO_RECONNECT)) {
                // to see if we can get back in touch with the service.
                return new InputBindResult(null, null, mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
            } else {
                EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId, SystemClock.uptimeMillis() - mLastBindTime, 0);
            }
        }
    }
    try {
        return startInputInnerLocked();
    } catch (RuntimeException e) {
        Slog.w(TAG, "Unexpected exception", e);
        return null;
    }
}
Also used : InputBindResult(com.android.internal.view.InputBindResult)

Aggregations

InputBindResult (com.android.internal.view.InputBindResult)37 RemoteException (android.os.RemoteException)25 Handler (android.os.Handler)7 View (android.view.View)7 PendingIntent (android.app.PendingIntent)6 Intent (android.content.Intent)6 Binder (android.os.Binder)6 IBinder (android.os.IBinder)6 InputChannel (android.view.InputChannel)6 InputMethodInfo (android.view.inputmethod.InputMethodInfo)6 SomeArgs (com.android.internal.os.SomeArgs)6 IInputContext (com.android.internal.view.IInputContext)6 IInputMethod (com.android.internal.view.IInputMethod)6 IInputMethodClient (com.android.internal.view.IInputMethodClient)6 IInputSessionCallback (com.android.internal.view.IInputSessionCallback)6 EditorInfo (android.view.inputmethod.EditorInfo)5