Merge "Transfer IME callbacks when app's focused root view changes." into tm-dev am: f15480984d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18417321

Change-Id: I5a539668696a4c77beb7c63c0808296c88e2d3f9
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Shan Huang
2022-05-18 21:18:09 +00:00
committed by Automerger Merge Worker
3 changed files with 55 additions and 11 deletions

View File

@@ -782,6 +782,7 @@ public final class InputMethodManager {
@Override
public void setCurrentRootView(ViewRootImpl rootView) {
synchronized (mH) {
mImeDispatcher.switchRootView(mCurRootView, rootView);
mCurRootView = rootView;
}
}

View File

@@ -25,8 +25,9 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.Log;
import android.view.ViewRootImpl;
import java.util.HashMap;
import java.util.ArrayList;
/**
* A {@link OnBackInvokedDispatcher} for IME that forwards {@link OnBackInvokedCallback}
@@ -117,7 +118,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
}
};
private final HashMap<Integer, OnBackInvokedCallback> mImeCallbackMap = new HashMap<>();
private final ArrayList<ImeOnBackInvokedCallback> mImeCallbacks = new ArrayList<>();
private void receive(
int resultCode, Bundle resultData,
@@ -140,39 +141,55 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
int callbackId,
@NonNull OnBackInvokedDispatcher receivingDispatcher) {
final ImeOnBackInvokedCallback imeCallback =
new ImeOnBackInvokedCallback(iCallback);
mImeCallbackMap.put(callbackId, imeCallback);
new ImeOnBackInvokedCallback(iCallback, callbackId, priority);
mImeCallbacks.add(imeCallback);
receivingDispatcher.registerOnBackInvokedCallback(priority, imeCallback);
}
private void unregisterReceivedCallback(
int callbackId, OnBackInvokedDispatcher receivingDispatcher) {
final OnBackInvokedCallback callback = mImeCallbackMap.get(callbackId);
ImeOnBackInvokedCallback callback = null;
for (ImeOnBackInvokedCallback imeCallback : mImeCallbacks) {
if (imeCallback.getId() == callbackId) {
callback = imeCallback;
break;
}
}
if (callback == null) {
Log.e(TAG, "Ime callback not found. Ignoring unregisterReceivedCallback. "
+ "callbackId: " + callbackId);
return;
}
receivingDispatcher.unregisterOnBackInvokedCallback(callback);
mImeCallbacks.remove(callback);
}
/** Clears all registered callbacks on the instance. */
public void clear() {
// Unregister previously registered callbacks if there's any.
if (getReceivingDispatcher() != null) {
for (OnBackInvokedCallback callback : mImeCallbackMap.values()) {
for (ImeOnBackInvokedCallback callback : mImeCallbacks) {
getReceivingDispatcher().unregisterOnBackInvokedCallback(callback);
}
}
mImeCallbackMap.clear();
mImeCallbacks.clear();
}
static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
@NonNull
private final IOnBackInvokedCallback mIOnBackInvokedCallback;
/**
* The hashcode of the callback instance in the IME process, used as a unique id to
* identify the callback when it's passed between processes.
*/
private final int mId;
private final int mPriority;
ImeOnBackInvokedCallback(@NonNull IOnBackInvokedCallback iCallback) {
ImeOnBackInvokedCallback(@NonNull IOnBackInvokedCallback iCallback, int id,
@Priority int priority) {
mIOnBackInvokedCallback = iCallback;
mId = id;
mPriority = priority;
}
@Override
@@ -186,8 +203,33 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
}
}
private int getId() {
return mId;
}
IOnBackInvokedCallback getIOnBackInvokedCallback() {
return mIOnBackInvokedCallback;
}
}
/**
* Transfers {@link ImeOnBackInvokedCallback}s registered on one {@link ViewRootImpl} to
* another {@link ViewRootImpl} on focus change.
*
* @param previous the previously focused {@link ViewRootImpl}.
* @param current the currently focused {@link ViewRootImpl}.
*/
// TODO(b/232845902): Add CTS to test IME back behavior when there's root view change while
// IME is up.
public void switchRootView(ViewRootImpl previous, ViewRootImpl current) {
for (ImeOnBackInvokedCallback imeCallback : mImeCallbacks) {
if (previous != null) {
previous.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(imeCallback);
}
if (current != null) {
current.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
imeCallback.mPriority, imeCallback);
}
}
}
}

View File

@@ -157,15 +157,16 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
/** Clears all registered callbacks on the instance. */
public void clear() {
if (mImeDispatcher != null) {
mImeDispatcher.clear();
mImeDispatcher = null;
}
if (!mAllCallbacks.isEmpty()) {
// Clear binder references in WM.
setTopOnBackInvokedCallback(null);
}
mAllCallbacks.clear();
mOnBackInvokedCallbacks.clear();
if (mImeDispatcher != null) {
mImeDispatcher = null;
}
}
private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {