Use DisplayContext to obtain InputMethodManager in ViewRootImpl

Historically ViewRootImpl#mContext has been just pointing to the
Context instance associated with whatever first View instance that is
being added to a Window.  In other words, ViewRootImpl#mContext is not
owned by ViewRootImpl.

This can become a problem if ViewRootImpl is moved from a display to
another display with ViewRootImpl#updateInternalDisplay(), which was
added last year to support multiple displays [1], because there is no
guarantee that the target Contaxt that is pointed from
ViewRootImpl#mContext is also updated to have the new display ID.

In order to support multi-display we need to use the right Context at
least when interacting with InputMethodManager. Hence as a short term
solution this CL introduces ViewRootImpl#mDisplayContext so that the
right instance of InputMethodManager can receive callback from
ViewRootImpl. In this way, we can make sure that the behavior change
in ViewRootImple is limited to how InputMethodManager instance is
obtained.

Longer term solution will be discussed in Bug 116349163.

 [1]: I9a9501cab788623ada15a31efb53e4b2378639fe
      b047b8bd7e

Bug: 115893206
Test: atest ActivityManagerMultiDisplayTests
Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases
Change-Id: Ifa0ca24e9cf764caf492ee065606680b6a06751a
This commit is contained in:
Yohei Yukawa
2018-09-25 15:19:38 -07:00
parent 2bfca321cc
commit bf25f9ed4e

View File

@@ -239,6 +239,12 @@ public final class ViewRootImpl implements ViewParent,
final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
@UnsupportedAppUsage
final Context mContext;
/**
* TODO(b/116349163): Check if we can merge this into {@link #mContext}.
*/
@NonNull
private Context mDisplayContext;
@UnsupportedAppUsage
final IWindowSession mWindowSession;
@NonNull Display mDisplay;
@@ -532,6 +538,7 @@ public final class ViewRootImpl implements ViewParent,
public ViewRootImpl(Context context, Display display) {
mContext = context;
mDisplayContext = context.createDisplayContext(display);
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
@@ -1249,6 +1256,7 @@ public final class ViewRootImpl implements ViewParent,
} else {
mDisplay = preferredDisplay;
}
mDisplayContext = mContext.createDisplayContext(mDisplay);
}
void pokeDrawLockIfNeeded() {
@@ -2579,7 +2587,7 @@ public final class ViewRootImpl implements ViewParent,
.mayUseInputMethod(mWindowAttributes.flags);
if (imTarget != mLastWasImTarget) {
mLastWasImTarget = imTarget;
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
if (imm != null && imTarget) {
imm.onPreWindowFocus(mView, hasWindowFocus);
imm.onPostWindowFocus(mView, mView.findFocus(),
@@ -2695,7 +2703,7 @@ public final class ViewRootImpl implements ViewParent,
mLastWasImTarget = WindowManager.LayoutParams
.mayUseInputMethod(mWindowAttributes.flags);
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
imm.onPreWindowFocus(mView, hasWindowFocus);
}
@@ -4329,7 +4337,8 @@ public final class ViewRootImpl implements ViewParent,
enqueueInputEvent(event, null, 0, true);
} break;
case MSG_CHECK_FOCUS: {
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
InputMethodManager imm =
mDisplayContext.getSystemService(InputMethodManager.class);
if (imm != null) {
imm.checkFocus();
}
@@ -4871,7 +4880,7 @@ public final class ViewRootImpl implements ViewParent,
@Override
protected int onProcess(QueuedInputEvent q) {
if (mLastWasImTarget && !isInLocalFocusMode()) {
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
if (imm != null) {
final InputEvent event = q.mEvent;
if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);