Merge "Transfer IME callbacks when app's focused root view changes." into tm-dev
This commit is contained in:
@@ -782,6 +782,7 @@ public final class InputMethodManager {
|
|||||||
@Override
|
@Override
|
||||||
public void setCurrentRootView(ViewRootImpl rootView) {
|
public void setCurrentRootView(ViewRootImpl rootView) {
|
||||||
synchronized (mH) {
|
synchronized (mH) {
|
||||||
|
mImeDispatcher.switchRootView(mCurRootView, rootView);
|
||||||
mCurRootView = rootView;
|
mCurRootView = rootView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ import android.os.Parcelable;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.util.Log;
|
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}
|
* 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(
|
private void receive(
|
||||||
int resultCode, Bundle resultData,
|
int resultCode, Bundle resultData,
|
||||||
@@ -140,39 +141,55 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
|
|||||||
int callbackId,
|
int callbackId,
|
||||||
@NonNull OnBackInvokedDispatcher receivingDispatcher) {
|
@NonNull OnBackInvokedDispatcher receivingDispatcher) {
|
||||||
final ImeOnBackInvokedCallback imeCallback =
|
final ImeOnBackInvokedCallback imeCallback =
|
||||||
new ImeOnBackInvokedCallback(iCallback);
|
new ImeOnBackInvokedCallback(iCallback, callbackId, priority);
|
||||||
mImeCallbackMap.put(callbackId, imeCallback);
|
mImeCallbacks.add(imeCallback);
|
||||||
receivingDispatcher.registerOnBackInvokedCallback(priority, imeCallback);
|
receivingDispatcher.registerOnBackInvokedCallback(priority, imeCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unregisterReceivedCallback(
|
private void unregisterReceivedCallback(
|
||||||
int callbackId, OnBackInvokedDispatcher receivingDispatcher) {
|
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) {
|
if (callback == null) {
|
||||||
Log.e(TAG, "Ime callback not found. Ignoring unregisterReceivedCallback. "
|
Log.e(TAG, "Ime callback not found. Ignoring unregisterReceivedCallback. "
|
||||||
+ "callbackId: " + callbackId);
|
+ "callbackId: " + callbackId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
receivingDispatcher.unregisterOnBackInvokedCallback(callback);
|
receivingDispatcher.unregisterOnBackInvokedCallback(callback);
|
||||||
|
mImeCallbacks.remove(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clears all registered callbacks on the instance. */
|
/** Clears all registered callbacks on the instance. */
|
||||||
public void clear() {
|
public void clear() {
|
||||||
// Unregister previously registered callbacks if there's any.
|
// Unregister previously registered callbacks if there's any.
|
||||||
if (getReceivingDispatcher() != null) {
|
if (getReceivingDispatcher() != null) {
|
||||||
for (OnBackInvokedCallback callback : mImeCallbackMap.values()) {
|
for (ImeOnBackInvokedCallback callback : mImeCallbacks) {
|
||||||
getReceivingDispatcher().unregisterOnBackInvokedCallback(callback);
|
getReceivingDispatcher().unregisterOnBackInvokedCallback(callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mImeCallbackMap.clear();
|
mImeCallbacks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
|
static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
|
||||||
@NonNull
|
@NonNull
|
||||||
private final IOnBackInvokedCallback mIOnBackInvokedCallback;
|
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;
|
mIOnBackInvokedCallback = iCallback;
|
||||||
|
mId = id;
|
||||||
|
mPriority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -186,8 +203,33 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getId() {
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
IOnBackInvokedCallback getIOnBackInvokedCallback() {
|
IOnBackInvokedCallback getIOnBackInvokedCallback() {
|
||||||
return mIOnBackInvokedCallback;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,15 +157,16 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
|||||||
|
|
||||||
/** Clears all registered callbacks on the instance. */
|
/** Clears all registered callbacks on the instance. */
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
if (mImeDispatcher != null) {
|
||||||
|
mImeDispatcher.clear();
|
||||||
|
mImeDispatcher = null;
|
||||||
|
}
|
||||||
if (!mAllCallbacks.isEmpty()) {
|
if (!mAllCallbacks.isEmpty()) {
|
||||||
// Clear binder references in WM.
|
// Clear binder references in WM.
|
||||||
setTopOnBackInvokedCallback(null);
|
setTopOnBackInvokedCallback(null);
|
||||||
}
|
}
|
||||||
mAllCallbacks.clear();
|
mAllCallbacks.clear();
|
||||||
mOnBackInvokedCallbacks.clear();
|
mOnBackInvokedCallbacks.clear();
|
||||||
if (mImeDispatcher != null) {
|
|
||||||
mImeDispatcher = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {
|
private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {
|
||||||
|
|||||||
Reference in New Issue
Block a user