Merge "Migrate IME to handle back with OnBackInvokedDispatcher." into tm-dev am: e3a61826eb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17952046 Change-Id: I8b92457b1d40be20e666f153249d6c72da7bc684 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -800,6 +800,7 @@ package android.content.pm {
|
||||
method public boolean hasRequestForegroundServiceExemption();
|
||||
method public boolean isPrivilegedApp();
|
||||
method public boolean isSystemApp();
|
||||
method public void setEnableOnBackInvokedCallback(boolean);
|
||||
field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8
|
||||
field public int privateFlags;
|
||||
}
|
||||
|
||||
@@ -2752,4 +2752,21 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the application will use the {@link android.window.OnBackInvokedCallback}
|
||||
* navigation system instead of the {@link android.view.KeyEvent#KEYCODE_BACK} and related
|
||||
* callbacks. Intended to be used from tests only.
|
||||
*
|
||||
* @see #isOnBackInvokedCallbackEnabled()
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void setEnableOnBackInvokedCallback(boolean isEnable) {
|
||||
if (isEnable) {
|
||||
privateFlagsExt |= PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
|
||||
} else {
|
||||
privateFlagsExt &= ~PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
import android.view.inputmethod.InputMethodSession;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.inputmethod.CancellationGroup;
|
||||
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
|
||||
@@ -194,7 +195,9 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
case DO_START_INPUT: {
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
final IBinder startInputToken = (IBinder) args.arg1;
|
||||
final IInputContext inputContext = (IInputContext) args.arg2;
|
||||
final IInputContext inputContext = (IInputContext) ((SomeArgs) args.arg2).arg1;
|
||||
final ImeOnBackInvokedDispatcher imeDispatcher =
|
||||
(ImeOnBackInvokedDispatcher) ((SomeArgs) args.arg2).arg2;
|
||||
final EditorInfo info = (EditorInfo) args.arg3;
|
||||
final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
|
||||
final boolean restarting = args.argi5 == 1;
|
||||
@@ -205,7 +208,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
: null;
|
||||
info.makeCompatible(mTargetSdkVersion);
|
||||
inputMethod.dispatchStartInputWithToken(ic, info, restarting, startInputToken,
|
||||
navButtonFlags);
|
||||
navButtonFlags, imeDispatcher);
|
||||
args.recycle();
|
||||
return;
|
||||
}
|
||||
@@ -348,13 +351,17 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
@Override
|
||||
public void startInput(IBinder startInputToken, IInputContext inputContext,
|
||||
EditorInfo attribute, boolean restarting,
|
||||
@InputMethodNavButtonFlags int navButtonFlags) {
|
||||
@InputMethodNavButtonFlags int navButtonFlags,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
if (mCancellationGroup == null) {
|
||||
Log.e(TAG, "startInput must be called after bindInput.");
|
||||
mCancellationGroup = new CancellationGroup();
|
||||
}
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = inputContext;
|
||||
args.arg2 = imeDispatcher;
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOII(DO_START_INPUT, startInputToken,
|
||||
inputContext, attribute, mCancellationGroup, restarting ? 1 : 0, navButtonFlags));
|
||||
args, attribute, mCancellationGroup, restarting ? 1 : 0, navButtonFlags));
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
|
||||
@@ -101,6 +101,7 @@ import android.view.BatchedInputEventReceiver.SimpleBatchedInputEventReceiver;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Gravity;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
@@ -134,6 +135,9 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
import android.window.OnBackInvokedCallback;
|
||||
import android.window.OnBackInvokedDispatcher;
|
||||
import android.window.WindowMetricsHelper;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -344,6 +348,9 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view.
|
||||
**/
|
||||
private RingBuffer<MotionEvent> mPendingEvents;
|
||||
private ImeOnBackInvokedDispatcher mImeDispatcher;
|
||||
private Boolean mBackCallbackRegistered = false;
|
||||
private final OnBackInvokedCallback mCompatBackCallback = this::compatHandleBack;
|
||||
|
||||
/**
|
||||
* Returns whether {@link InputMethodService} is responsible for rendering the back button and
|
||||
@@ -797,7 +804,13 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
@Override
|
||||
public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
|
||||
@NonNull EditorInfo editorInfo, boolean restarting,
|
||||
@NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags) {
|
||||
@NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
mImeDispatcher = imeDispatcher;
|
||||
if (mWindow != null) {
|
||||
mWindow.getOnBackInvokedDispatcher().setImeOnBackInvokedDispatcher(
|
||||
imeDispatcher);
|
||||
}
|
||||
mPrivOps.reportStartInputAsync(startInputToken);
|
||||
mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags);
|
||||
if (restarting) {
|
||||
@@ -1496,6 +1509,10 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initSoftInputWindow");
|
||||
mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
|
||||
if (mImeDispatcher != null) {
|
||||
mWindow.getOnBackInvokedDispatcher()
|
||||
.setImeOnBackInvokedDispatcher(mImeDispatcher);
|
||||
}
|
||||
mNavigationBarController.onSoftInputWindowCreated(mWindow);
|
||||
{
|
||||
final Window window = mWindow.getWindow();
|
||||
@@ -1608,6 +1625,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
// when IME developers are doing something unsupported.
|
||||
InputMethodPrivilegedOperationsRegistry.remove(mToken);
|
||||
}
|
||||
unregisterCompatOnBackInvokedCallback();
|
||||
mImeDispatcher = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2568,9 +2587,47 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
cancelImeSurfaceRemoval();
|
||||
mInShowWindow = false;
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
registerCompatOnBackInvokedCallback();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers an {@link OnBackInvokedCallback} to handle back invocation when ahead-of-time
|
||||
* back dispatching is enabled. We keep the {@link KeyEvent#KEYCODE_BACK} based legacy code
|
||||
* around to handle back on older devices.
|
||||
*/
|
||||
private void registerCompatOnBackInvokedCallback() {
|
||||
if (mBackCallbackRegistered) {
|
||||
return;
|
||||
}
|
||||
if (mWindow != null) {
|
||||
mWindow.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatBackCallback);
|
||||
mBackCallbackRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterCompatOnBackInvokedCallback() {
|
||||
if (!mBackCallbackRegistered) {
|
||||
return;
|
||||
}
|
||||
if (mWindow != null) {
|
||||
mWindow.getOnBackInvokedDispatcher()
|
||||
.unregisterOnBackInvokedCallback(mCompatBackCallback);
|
||||
mBackCallbackRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
private KeyEvent createBackKeyEvent(int action, boolean isTracking) {
|
||||
final long when = SystemClock.uptimeMillis();
|
||||
return new KeyEvent(when, when, action,
|
||||
KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
|
||||
KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
|
||||
KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY
|
||||
| (isTracking ? KeyEvent.FLAG_TRACKING : 0),
|
||||
InputDevice.SOURCE_KEYBOARD);
|
||||
}
|
||||
|
||||
private boolean prepareWindow(boolean showInput) {
|
||||
boolean doShowInput = false;
|
||||
mDecorViewVisible = true;
|
||||
@@ -2658,6 +2715,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
}
|
||||
mLastWasInFullscreenMode = mIsFullscreen;
|
||||
updateFullscreenMode();
|
||||
unregisterCompatOnBackInvokedCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3797,4 +3855,14 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
proto.end(token);
|
||||
}
|
||||
};
|
||||
|
||||
private void compatHandleBack() {
|
||||
final KeyEvent downEvent = createBackKeyEvent(
|
||||
KeyEvent.ACTION_DOWN, false /* isTracking */);
|
||||
onKeyDown(KeyEvent.KEYCODE_BACK, downEvent);
|
||||
final boolean hasStartedTracking =
|
||||
(downEvent.getFlags() & KeyEvent.FLAG_START_TRACKING) != 0;
|
||||
final KeyEvent upEvent = createBackKeyEvent(KeyEvent.ACTION_UP, hasStartedTracking);
|
||||
onKeyUp(KeyEvent.KEYCODE_BACK, upEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6095,6 +6095,28 @@ public final class ViewRootImpl implements ViewParent,
|
||||
|
||||
@Override
|
||||
protected int onProcess(QueuedInputEvent q) {
|
||||
if (q.mEvent instanceof KeyEvent) {
|
||||
final KeyEvent event = (KeyEvent) q.mEvent;
|
||||
|
||||
// If the new back dispatch is enabled, intercept KEYCODE_BACK before it reaches the
|
||||
// view tree or IME, and invoke the appropriate {@link OnBackInvokedCallback}.
|
||||
if (isBack(event)
|
||||
&& mContext != null
|
||||
&& WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
|
||||
OnBackInvokedCallback topCallback =
|
||||
getOnBackInvokedDispatcher().getTopCallback();
|
||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
if (topCallback != null) {
|
||||
topCallback.onBackInvoked();
|
||||
return FINISH_HANDLED;
|
||||
}
|
||||
} else {
|
||||
// Drop other actions such as {@link KeyEvent.ACTION_DOWN}.
|
||||
return FINISH_NOT_HANDLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mInputQueue != null && q.mEvent instanceof KeyEvent) {
|
||||
mInputQueue.sendInputEvent(q.mEvent, q, true, this);
|
||||
return DEFER;
|
||||
@@ -6446,24 +6468,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
return FINISH_HANDLED;
|
||||
}
|
||||
|
||||
// If the new back dispatch is enabled, intercept KEYCODE_BACK before it reaches the
|
||||
// view tree and invoke the appropriate {@link OnBackInvokedCallback}.
|
||||
if (isBack(event)
|
||||
&& mContext != null
|
||||
&& WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
|
||||
OnBackInvokedCallback topCallback =
|
||||
getOnBackInvokedDispatcher().getTopCallback();
|
||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
if (topCallback != null) {
|
||||
topCallback.onBackInvoked();
|
||||
return FINISH_HANDLED;
|
||||
}
|
||||
} else {
|
||||
// Drop other actions such as {@link KeyEvent.ACTION_DOWN}.
|
||||
return FINISH_NOT_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
// Deliver the key to the view hierarchy.
|
||||
if (mView.dispatchKeyEvent(event)) {
|
||||
return FINISH_HANDLED;
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.util.Log;
|
||||
import android.view.InputChannel;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
|
||||
import com.android.internal.inputmethod.InputMethodNavButtonFlags;
|
||||
@@ -232,6 +233,10 @@ public interface InputMethod {
|
||||
* long as your implementation of {@link InputMethod} relies on such
|
||||
* IPCs
|
||||
* @param navButtonFlags {@link InputMethodNavButtonFlags} in the initial state of this session.
|
||||
* @param imeDispatcher The {@link ImeOnBackInvokedDispatcher }} to be set on the
|
||||
* IME's {@link android.window.WindowOnBackInvokedDispatcher}, so that IME
|
||||
* {@link android.window.OnBackInvokedCallback}s can be forwarded to
|
||||
* the client requesting to start input.
|
||||
* @see #startInput(InputConnection, EditorInfo)
|
||||
* @see #restartInput(InputConnection, EditorInfo)
|
||||
* @see EditorInfo
|
||||
@@ -240,7 +245,8 @@ public interface InputMethod {
|
||||
@MainThread
|
||||
default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
|
||||
@NonNull EditorInfo editorInfo, boolean restarting,
|
||||
@NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags) {
|
||||
@NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
if (restarting) {
|
||||
restartInput(inputConnection, editorInfo);
|
||||
} else {
|
||||
|
||||
@@ -91,6 +91,8 @@ import android.view.View;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
||||
import android.view.autofill.AutofillManager;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
import android.window.WindowOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.inputmethod.DirectBootAwareness;
|
||||
@@ -105,6 +107,7 @@ import com.android.internal.inputmethod.StartInputFlags;
|
||||
import com.android.internal.inputmethod.StartInputReason;
|
||||
import com.android.internal.inputmethod.UnbindReason;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.view.IInputContext;
|
||||
import com.android.internal.view.IInputMethodClient;
|
||||
import com.android.internal.view.IInputMethodManager;
|
||||
import com.android.internal.view.IInputMethodSession;
|
||||
@@ -278,6 +281,21 @@ public final class InputMethodManager {
|
||||
*/
|
||||
private static final String SUBTYPE_MODE_VOICE = "voice";
|
||||
|
||||
/**
|
||||
* Provide this to {@link IInputMethodManager#startInputOrWindowGainedFocus(
|
||||
* int, IInputMethodClient, IBinder, int, int, int, EditorInfo, IInputContext, int)} to receive
|
||||
* {@link android.window.OnBackInvokedCallback} registrations from IME.
|
||||
*/
|
||||
private final ImeOnBackInvokedDispatcher mImeDispatcher =
|
||||
new ImeOnBackInvokedDispatcher(Handler.getMain()) {
|
||||
@Override
|
||||
public WindowOnBackInvokedDispatcher getReceivingDispatcher() {
|
||||
synchronized (mH) {
|
||||
return mCurRootView != null ? mCurRootView.getOnBackInvokedDispatcher() : null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
|
||||
* or indirectly relied on {@link #sInstance} via reflection or something like that.
|
||||
@@ -740,7 +758,8 @@ public final class InputMethodManager {
|
||||
windowFlags,
|
||||
null,
|
||||
null, null,
|
||||
mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
|
||||
mCurRootView.mContext.getApplicationInfo().targetSdkVersion,
|
||||
mImeDispatcher);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -1687,6 +1706,8 @@ public final class InputMethodManager {
|
||||
mServedConnecting = false;
|
||||
clearConnectionLocked();
|
||||
}
|
||||
// Clear the back callbacks held by the ime dispatcher to avoid memory leaks.
|
||||
mImeDispatcher.clear();
|
||||
}
|
||||
|
||||
public void displayCompletions(View view, CompletionInfo[] completions) {
|
||||
@@ -2359,7 +2380,8 @@ public final class InputMethodManager {
|
||||
softInputMode, windowFlags, tba, servedInputConnection,
|
||||
servedInputConnection == null ? null
|
||||
: servedInputConnection.asIRemoteAccessibilityInputConnection(),
|
||||
view.getContext().getApplicationInfo().targetSdkVersion);
|
||||
view.getContext().getApplicationInfo().targetSdkVersion,
|
||||
mImeDispatcher);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
20
core/java/android/window/ImeOnBackInvokedDispatcher.aidl
Normal file
20
core/java/android/window/ImeOnBackInvokedDispatcher.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/* //device/java/android/android/os/ParcelFileDescriptor.aidl
|
||||
**
|
||||
** Copyright 2022, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
package android.window;
|
||||
|
||||
parcelable ImeOnBackInvokedDispatcher;
|
||||
187
core/java/android/window/ImeOnBackInvokedDispatcher.java
Normal file
187
core/java/android/window/ImeOnBackInvokedDispatcher.java
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.window;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A {@link OnBackInvokedDispatcher} for IME that forwards {@link OnBackInvokedCallback}
|
||||
* registrations from the IME process to the app process to be registered on the app window.
|
||||
* <p>
|
||||
* The app process creates and propagates an instance of {@link ImeOnBackInvokedDispatcher}
|
||||
* to the IME to be set on the IME window's {@link WindowOnBackInvokedDispatcher}.
|
||||
* <p>
|
||||
* @see WindowOnBackInvokedDispatcher#setImeOnBackInvokedDispatcher
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parcelable {
|
||||
|
||||
private static final String TAG = "ImeBackDispatcher";
|
||||
static final String RESULT_KEY_ID = "id";
|
||||
static final String RESULT_KEY_CALLBACK = "callback";
|
||||
static final String RESULT_KEY_PRIORITY = "priority";
|
||||
static final int RESULT_CODE_REGISTER = 0;
|
||||
static final int RESULT_CODE_UNREGISTER = 1;
|
||||
@NonNull
|
||||
private final ResultReceiver mResultReceiver;
|
||||
|
||||
public ImeOnBackInvokedDispatcher(Handler handler) {
|
||||
mResultReceiver = new ResultReceiver(handler) {
|
||||
@Override
|
||||
public void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
WindowOnBackInvokedDispatcher dispatcher = getReceivingDispatcher();
|
||||
if (dispatcher != null) {
|
||||
receive(resultCode, resultData, dispatcher);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to return the {@link WindowOnBackInvokedDispatcher} of the window
|
||||
* that should receive the forwarded callback.
|
||||
*/
|
||||
@Nullable
|
||||
protected WindowOnBackInvokedDispatcher getReceivingDispatcher() {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImeOnBackInvokedDispatcher(Parcel in) {
|
||||
mResultReceiver = in.readTypedObject(ResultReceiver.CREATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOnBackInvokedCallback(
|
||||
@OnBackInvokedDispatcher.Priority int priority,
|
||||
@NonNull OnBackInvokedCallback callback) {
|
||||
final Bundle bundle = new Bundle();
|
||||
final IOnBackInvokedCallback iCallback =
|
||||
new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback);
|
||||
bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
|
||||
bundle.putInt(RESULT_KEY_PRIORITY, priority);
|
||||
bundle.putInt(RESULT_KEY_ID, callback.hashCode());
|
||||
mResultReceiver.send(RESULT_CODE_REGISTER, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterOnBackInvokedCallback(
|
||||
@NonNull OnBackInvokedCallback callback) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(RESULT_KEY_ID, callback.hashCode());
|
||||
mResultReceiver.send(RESULT_CODE_UNREGISTER, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeTypedObject(mResultReceiver, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<ImeOnBackInvokedDispatcher> CREATOR =
|
||||
new Parcelable.Creator<ImeOnBackInvokedDispatcher>() {
|
||||
public ImeOnBackInvokedDispatcher createFromParcel(Parcel in) {
|
||||
return new ImeOnBackInvokedDispatcher(in);
|
||||
}
|
||||
public ImeOnBackInvokedDispatcher[] newArray(int size) {
|
||||
return new ImeOnBackInvokedDispatcher[size];
|
||||
}
|
||||
};
|
||||
|
||||
private final HashMap<Integer, OnBackInvokedCallback> mImeCallbackMap = new HashMap<>();
|
||||
|
||||
private void receive(
|
||||
int resultCode, Bundle resultData,
|
||||
@NonNull OnBackInvokedDispatcher receivingDispatcher) {
|
||||
final int callbackId = resultData.getInt(RESULT_KEY_ID);
|
||||
if (resultCode == RESULT_CODE_REGISTER) {
|
||||
int priority = resultData.getInt(RESULT_KEY_PRIORITY);
|
||||
final IOnBackInvokedCallback callback = IOnBackInvokedCallback.Stub.asInterface(
|
||||
resultData.getBinder(RESULT_KEY_CALLBACK));
|
||||
registerReceivedCallback(
|
||||
callback, priority, callbackId, receivingDispatcher);
|
||||
} else if (resultCode == RESULT_CODE_UNREGISTER) {
|
||||
unregisterReceivedCallback(callbackId, receivingDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReceivedCallback(
|
||||
@NonNull IOnBackInvokedCallback iCallback,
|
||||
@OnBackInvokedDispatcher.Priority int priority,
|
||||
int callbackId,
|
||||
@NonNull OnBackInvokedDispatcher receivingDispatcher) {
|
||||
final ImeOnBackInvokedCallback imeCallback =
|
||||
new ImeOnBackInvokedCallback(iCallback);
|
||||
mImeCallbackMap.put(callbackId, imeCallback);
|
||||
receivingDispatcher.registerOnBackInvokedCallback(priority, imeCallback);
|
||||
}
|
||||
|
||||
private void unregisterReceivedCallback(
|
||||
int callbackId, OnBackInvokedDispatcher receivingDispatcher) {
|
||||
final OnBackInvokedCallback callback = mImeCallbackMap.get(callbackId);
|
||||
if (callback == null) {
|
||||
Log.e(TAG, "Ime callback not found. Ignoring unregisterReceivedCallback. "
|
||||
+ "callbackId: " + callbackId);
|
||||
return;
|
||||
}
|
||||
receivingDispatcher.unregisterOnBackInvokedCallback(callback);
|
||||
}
|
||||
|
||||
/** Clears all registered callbacks on the instance. */
|
||||
public void clear() {
|
||||
mImeCallbackMap.clear();
|
||||
}
|
||||
|
||||
static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
|
||||
@NonNull
|
||||
private final IOnBackInvokedCallback mIOnBackInvokedCallback;
|
||||
|
||||
ImeOnBackInvokedCallback(@NonNull IOnBackInvokedCallback iCallback) {
|
||||
mIOnBackInvokedCallback = iCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
try {
|
||||
if (mIOnBackInvokedCallback != null) {
|
||||
mIOnBackInvokedCallback.onBackInvoked();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Exception when invoking forwarded callback. e: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
IOnBackInvokedCallback getIOnBackInvokedCallback() {
|
||||
return mIOnBackInvokedCallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,4 +96,19 @@ public interface OnBackInvokedDispatcher {
|
||||
* @hide
|
||||
*/
|
||||
default void registerSystemOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) { }
|
||||
|
||||
|
||||
/**
|
||||
* Sets an {@link ImeOnBackInvokedDispatcher} to forward {@link OnBackInvokedCallback}s
|
||||
* from IME to the app process to be registered on the app window.
|
||||
*
|
||||
* Only call this on the IME window. Create the {@link ImeOnBackInvokedDispatcher} from
|
||||
* the application process and override
|
||||
* {@link ImeOnBackInvokedDispatcher#getReceivingDispatcher()} to point to the app
|
||||
* window's {@link WindowOnBackInvokedDispatcher}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
default void setImeOnBackInvokedDispatcher(
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) { }
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
private final List<Pair<OnBackInvokedCallback, Integer>> mCallbacks = new ArrayList<>();
|
||||
private final Object mLock = new Object();
|
||||
private OnBackInvokedDispatcher mActualDispatcher = null;
|
||||
private ImeOnBackInvokedDispatcher mImeDispatcher;
|
||||
|
||||
@Override
|
||||
public void registerOnBackInvokedCallback(
|
||||
@@ -108,6 +109,9 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
Log.v(TAG, String.format("Proxy transferring %d callbacks to %s", mCallbacks.size(),
|
||||
mActualDispatcher));
|
||||
}
|
||||
if (mImeDispatcher != null) {
|
||||
mActualDispatcher.setImeOnBackInvokedDispatcher(mImeDispatcher);
|
||||
}
|
||||
for (Pair<OnBackInvokedCallback, Integer> callbackPair : mCallbacks) {
|
||||
int priority = callbackPair.second;
|
||||
if (priority >= 0) {
|
||||
@@ -117,6 +121,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
}
|
||||
}
|
||||
mCallbacks.clear();
|
||||
mImeDispatcher = null;
|
||||
}
|
||||
|
||||
private void clearCallbacksOnDispatcher() {
|
||||
@@ -142,6 +147,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mCallbacks.clear();
|
||||
mImeDispatcher = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,4 +175,14 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
transferCallbacksToDispatcher();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImeOnBackInvokedDispatcher(
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
if (mActualDispatcher != null) {
|
||||
mActualDispatcher.setImeOnBackInvokedDispatcher(imeDispatcher);
|
||||
} else {
|
||||
mImeDispatcher = imeDispatcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
.getInt("persist.wm.debug.predictive_back", 1) != 0;
|
||||
private static final boolean ALWAYS_ENFORCE_PREDICTIVE_BACK = SystemProperties
|
||||
.getInt("persist.wm.debug.predictive_back_always_enforce", 0) != 0;
|
||||
@Nullable
|
||||
private ImeOnBackInvokedDispatcher mImeDispatcher;
|
||||
|
||||
/** Convenience hashmap to quickly decide if a callback has been added. */
|
||||
private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
|
||||
@@ -94,6 +96,10 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
|
||||
private void registerOnBackInvokedCallbackUnchecked(
|
||||
@NonNull OnBackInvokedCallback callback, @Priority int priority) {
|
||||
if (mImeDispatcher != null) {
|
||||
mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
|
||||
return;
|
||||
}
|
||||
if (!mOnBackInvokedCallbacks.containsKey(priority)) {
|
||||
mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
|
||||
}
|
||||
@@ -120,6 +126,10 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
|
||||
@Override
|
||||
public void unregisterOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
|
||||
if (mImeDispatcher != null) {
|
||||
mImeDispatcher.unregisterOnBackInvokedCallback(callback);
|
||||
return;
|
||||
}
|
||||
if (!mAllCallbacks.containsKey(callback)) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Callback not found. returning...");
|
||||
@@ -153,6 +163,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
}
|
||||
mAllCallbacks.clear();
|
||||
mOnBackInvokedCallbacks.clear();
|
||||
if (mImeDispatcher != null) {
|
||||
mImeDispatcher = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {
|
||||
@@ -160,14 +173,18 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (callback == null) {
|
||||
mWindowSession.setOnBackInvokedCallbackInfo(mWindow, null);
|
||||
} else {
|
||||
OnBackInvokedCallbackInfo callbackInfo = null;
|
||||
if (callback != null) {
|
||||
int priority = mAllCallbacks.get(callback);
|
||||
mWindowSession.setOnBackInvokedCallbackInfo(
|
||||
mWindow, new OnBackInvokedCallbackInfo(
|
||||
new OnBackInvokedCallbackWrapper(callback), priority));
|
||||
final IOnBackInvokedCallback iCallback =
|
||||
callback instanceof ImeOnBackInvokedDispatcher
|
||||
.ImeOnBackInvokedCallback
|
||||
? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
|
||||
callback).getIOnBackInvokedCallback()
|
||||
: new OnBackInvokedCallbackWrapper(callback);
|
||||
callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
|
||||
}
|
||||
mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
|
||||
if (DEBUG && callback == null) {
|
||||
Log.d(TAG, TextUtils.formatSimple("setTopOnBackInvokedCallback(null) Callers:%s",
|
||||
Debug.getCallers(5, " ")));
|
||||
@@ -190,7 +207,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
|
||||
static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
|
||||
private final WeakReference<OnBackInvokedCallback> mCallback;
|
||||
|
||||
OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) {
|
||||
@@ -270,4 +287,10 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
|
||||
return featureFlagEnabled && (appRequestsPredictiveBack || ALWAYS_ENFORCE_PREDICTIVE_BACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImeOnBackInvokedDispatcher(
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
mImeDispatcher = imeDispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.view.MotionEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputBinding;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
|
||||
import com.android.internal.view.IInlineSuggestionsRequestCallback;
|
||||
import com.android.internal.view.IInputContext;
|
||||
@@ -47,7 +48,8 @@ oneway interface IInputMethod {
|
||||
void unbindInput();
|
||||
|
||||
void startInput(in IBinder startInputToken, in IInputContext inputContext,
|
||||
in EditorInfo attribute, boolean restarting, int navigationBarFlags);
|
||||
in EditorInfo attribute, boolean restarting, int navigationBarFlags,
|
||||
in ImeOnBackInvokedDispatcher imeDispatcher);
|
||||
|
||||
void onNavButtonFlagsChanged(int navButtonFlags);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.os.ResultReceiver;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.inputmethod.InputBindResult;
|
||||
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
|
||||
@@ -57,7 +58,7 @@ interface IInputMethodManager {
|
||||
/* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
|
||||
int windowFlags, in EditorInfo attribute, in IInputContext inputContext,
|
||||
in IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
|
||||
int unverifiedTargetSdkVersion);
|
||||
int unverifiedTargetSdkVersion, in ImeOnBackInvokedDispatcher imeDispatcher);
|
||||
|
||||
void showInputMethodPickerFromClient(in IInputMethodClient client,
|
||||
int auxiliarySubtypeMode);
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.view.MotionEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputBinding;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
|
||||
import com.android.internal.inputmethod.InputMethodNavButtonFlags;
|
||||
@@ -148,10 +149,11 @@ final class IInputMethodInvoker {
|
||||
|
||||
@AnyThread
|
||||
void startInput(IBinder startInputToken, IInputContext inputContext, EditorInfo attribute,
|
||||
boolean restarting, @InputMethodNavButtonFlags int navButtonFlags) {
|
||||
boolean restarting, @InputMethodNavButtonFlags int navButtonFlags,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
try {
|
||||
mTarget.startInput(startInputToken, inputContext, attribute, restarting,
|
||||
navButtonFlags);
|
||||
navButtonFlags, imeDispatcher);
|
||||
} catch (RemoteException e) {
|
||||
logRemoteException(e);
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTr
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.window.ImeOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
@@ -615,6 +616,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
*/
|
||||
IInputContext mCurInputContext;
|
||||
|
||||
/**
|
||||
* The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
|
||||
* receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
|
||||
*/
|
||||
ImeOnBackInvokedDispatcher mCurImeDispatcher;
|
||||
|
||||
/**
|
||||
* The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
|
||||
*/
|
||||
@@ -2623,7 +2630,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
final SessionState session = mCurClient.curSession;
|
||||
setEnabledSessionLocked(session);
|
||||
session.method.startInput(startInputToken, mCurInputContext, mCurAttribute, restarting,
|
||||
navButtonFlags);
|
||||
navButtonFlags, mCurImeDispatcher);
|
||||
if (mShowRequested) {
|
||||
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
|
||||
showCurrentInputLocked(mCurFocusedWindow, getAppShowFlagsLocked(), null,
|
||||
@@ -2733,7 +2740,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
|
||||
@NonNull EditorInfo attribute, @StartInputFlags int startInputFlags,
|
||||
@StartInputReason int startInputReason,
|
||||
int unverifiedTargetSdkVersion) {
|
||||
int unverifiedTargetSdkVersion,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
// If no method is currently selected, do nothing.
|
||||
final String selectedMethodId = getSelectedMethodIdLocked();
|
||||
if (selectedMethodId == null) {
|
||||
@@ -2777,6 +2785,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
mCurClient = cs;
|
||||
mCurInputContext = inputContext;
|
||||
mCurRemoteAccessibilityInputConnection = remoteAccessibilityInputConnection;
|
||||
mCurImeDispatcher = imeDispatcher;
|
||||
mCurVirtualDisplayToScreenMatrix =
|
||||
getVirtualDisplayToScreenMatrixLocked(cs.selfReportedDisplayId,
|
||||
mDisplayIdToShowIme);
|
||||
@@ -3780,10 +3789,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
|
||||
int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
|
||||
IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
|
||||
int unverifiedTargetSdkVersion) {
|
||||
int unverifiedTargetSdkVersion,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
return startInputOrWindowGainedFocusInternal(startInputReason, client, windowToken,
|
||||
startInputFlags, softInputMode, windowFlags, attribute, inputContext,
|
||||
remoteAccessibilityInputConnection, unverifiedTargetSdkVersion);
|
||||
remoteAccessibilityInputConnection, unverifiedTargetSdkVersion,
|
||||
imeDispatcher);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -3792,7 +3803,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
|
||||
int windowFlags, @Nullable EditorInfo attribute, @Nullable IInputContext inputContext,
|
||||
@Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
|
||||
int unverifiedTargetSdkVersion) {
|
||||
int unverifiedTargetSdkVersion,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
if (windowToken == null) {
|
||||
Slog.e(TAG, "windowToken cannot be null.");
|
||||
return InputBindResult.NULL;
|
||||
@@ -3829,7 +3841,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
result = startInputOrWindowGainedFocusInternalLocked(startInputReason,
|
||||
client, windowToken, startInputFlags, softInputMode, windowFlags,
|
||||
attribute, inputContext, remoteAccessibilityInputConnection,
|
||||
unverifiedTargetSdkVersion, userId);
|
||||
unverifiedTargetSdkVersion, userId, imeDispatcher);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -3857,7 +3869,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@SoftInputModeFlags int softInputMode, int windowFlags, EditorInfo attribute,
|
||||
IInputContext inputContext,
|
||||
@Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
|
||||
int unverifiedTargetSdkVersion, @UserIdInt int userId) {
|
||||
int unverifiedTargetSdkVersion, @UserIdInt int userId,
|
||||
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "startInputOrWindowGainedFocusInternalLocked: reason="
|
||||
+ InputMethodDebug.startInputReasonToString(startInputReason)
|
||||
@@ -3868,7 +3881,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
+ InputMethodDebug.startInputFlagsToString(startInputFlags)
|
||||
+ " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
|
||||
+ " windowFlags=#" + Integer.toHexString(windowFlags)
|
||||
+ " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion);
|
||||
+ " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion
|
||||
+ " imeDispatcher=" + imeDispatcher);
|
||||
}
|
||||
|
||||
final ClientState cs = mClients.get(client.asBinder());
|
||||
@@ -3952,7 +3966,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (attribute != null) {
|
||||
return startInputUncheckedLocked(cs, inputContext,
|
||||
remoteAccessibilityInputConnection, attribute, startInputFlags,
|
||||
startInputReason, unverifiedTargetSdkVersion);
|
||||
startInputReason, unverifiedTargetSdkVersion, imeDispatcher);
|
||||
}
|
||||
return new InputBindResult(
|
||||
InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
|
||||
@@ -3993,7 +4007,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (isTextEditor && attribute != null
|
||||
&& shouldRestoreImeVisibility(windowToken, softInputMode)) {
|
||||
res = startInputUncheckedLocked(cs, inputContext, remoteAccessibilityInputConnection,
|
||||
attribute, startInputFlags, startInputReason, unverifiedTargetSdkVersion);
|
||||
attribute, startInputFlags, startInputReason, unverifiedTargetSdkVersion,
|
||||
imeDispatcher);
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY);
|
||||
return res;
|
||||
@@ -4033,7 +4048,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (attribute != null) {
|
||||
res = startInputUncheckedLocked(cs, inputContext,
|
||||
remoteAccessibilityInputConnection, attribute, startInputFlags,
|
||||
startInputReason, unverifiedTargetSdkVersion);
|
||||
startInputReason, unverifiedTargetSdkVersion,
|
||||
imeDispatcher);
|
||||
didStart = true;
|
||||
}
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
@@ -4065,7 +4081,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (attribute != null) {
|
||||
res = startInputUncheckedLocked(cs, inputContext,
|
||||
remoteAccessibilityInputConnection, attribute, startInputFlags,
|
||||
startInputReason, unverifiedTargetSdkVersion);
|
||||
startInputReason, unverifiedTargetSdkVersion,
|
||||
imeDispatcher);
|
||||
didStart = true;
|
||||
}
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
@@ -4085,7 +4102,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (attribute != null) {
|
||||
res = startInputUncheckedLocked(cs, inputContext,
|
||||
remoteAccessibilityInputConnection, attribute, startInputFlags,
|
||||
startInputReason, unverifiedTargetSdkVersion);
|
||||
startInputReason, unverifiedTargetSdkVersion,
|
||||
imeDispatcher);
|
||||
didStart = true;
|
||||
}
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
@@ -4115,7 +4133,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
res = startInputUncheckedLocked(cs, inputContext,
|
||||
remoteAccessibilityInputConnection, attribute, startInputFlags,
|
||||
startInputReason, unverifiedTargetSdkVersion);
|
||||
startInputReason, unverifiedTargetSdkVersion,
|
||||
imeDispatcher);
|
||||
} else {
|
||||
res = InputBindResult.NULL_EDITOR_INFO;
|
||||
}
|
||||
|
||||
@@ -187,7 +187,6 @@ class BackNavigationController {
|
||||
if (backType == BackNavigationInfo.TYPE_CALLBACK
|
||||
|| currentActivity == null
|
||||
|| currentTask == null
|
||||
|| currentTask.getDisplayContent().getImeContainer().isVisible()
|
||||
|| currentActivity.isActivityTypeHome()) {
|
||||
return infoBuilder
|
||||
.setType(backType)
|
||||
|
||||
Reference in New Issue
Block a user