diff options
| author | 2018-10-14 19:24:31 +0800 | |
|---|---|---|
| committer | 2018-10-14 19:24:31 +0800 | |
| commit | 4b173140f30c801ab62e0d480d549ee9efa6ca33 (patch) | |
| tree | 34d9088be9e0725e911f28247f4c5adf506f1018 | |
| parent | 2422220258bf6bba02728581c7948d08c322d67a (diff) | |
Get InputMethodManager in View only if needed
The perf regression found in my initial attempt [1] to instantiate
InputMethodManager (IMM) for each display revieled that when a Window
gained/lost focus,
getContext().getSystemService(InputMethodManager.class)
gets called for all the View objects that belong to the Window.
This CL introduces a private utility method
View.notifyFocusChangeToInputMethodManager()
to replace existing unnecessary acquisitions of IMM in View.java,
including the most concerning one View.onWindowFocusChanged().
There should be no negative side-effect in doing this optimization.
LatencyTests results:
testExpandNotificationsLatency on taimen-userdebug
without this CL:
results=[43, 46, 58, 47, 52, 59, 55, 59, 58, 46]
min: 43.0, max:59.0, avg:54.7, median:53.5, std_dev:5.967
with this CL:
results=[41, 58, 55, 59, 60, 67, 51, 55, 55, 55]
min: 41.0, max:67.0, avg:55.6, median:55.0, std_dev:6.344
[1]: I7242e765426353672823fcc8277f20ac361930d7
c53d78e992694e471ddaae73f9a30977db9cdb75
Bug: 115893206
Test: atest ActivityManagerMultiDisplayTests
Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases
Test: atest FrameworksCoreTests:android.view.inputmethod.InputMethodManagerTest
Test: No perf regression observed in Bug 117434607
Change-Id: I5c64b23c3f5cb16f7f3fb9cdc2be063083566050
| -rw-r--r-- | core/java/android/view/View.java | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c18187b21200..29d3742ba632 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -7315,17 +7315,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Here we check whether we still need the default focus highlight, and switch it on/off. switchDefaultFocusHighlight(); - InputMethodManager imm = getContext().getSystemService(InputMethodManager.class); if (!gainFocus) { if (isPressed()) { setPressed(false); } - if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) { - imm.focusOut(this); + if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) { + notifyFocusChangeToInputMethodManager(false /* hasFocus */); } onFocusLost(); - } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) { - imm.focusIn(this); + } else if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) { + notifyFocusChangeToInputMethodManager(true /* hasFocus */); } invalidate(true); @@ -7341,6 +7340,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback, notifyEnterOrExitForAutoFillIfNeeded(gainFocus); } + /** + * Notify {@link InputMethodManager} about the focus change of the {@link View}. + * + * <p>Does nothing when {@link InputMethodManager} is not available.</p> + * + * @param hasFocus {@code true} when the {@link View} is being focused. + */ + private void notifyFocusChangeToInputMethodManager(boolean hasFocus) { + final InputMethodManager imm = + getContext().getSystemService(InputMethodManager.class); + if (imm == null) { + return; + } + if (hasFocus) { + imm.focusIn(this); + } else { + imm.focusOut(this); + } + } + /** @hide */ public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) { if (canNotifyAutofillEnterExitEvent()) { @@ -12485,7 +12504,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; onFinishTemporaryDetach(); if (hasWindowFocus() && hasFocus()) { - getContext().getSystemService(InputMethodManager.class).focusIn(this); + notifyFocusChangeToInputMethodManager(true /* hasFocus */); } notifyEnterOrExitForAutoFillIfNeeded(true); } @@ -12876,20 +12895,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * focus, false otherwise. */ public void onWindowFocusChanged(boolean hasWindowFocus) { - InputMethodManager imm = getContext().getSystemService(InputMethodManager.class); if (!hasWindowFocus) { if (isPressed()) { setPressed(false); } mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; - if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { - imm.focusOut(this); + if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { + notifyFocusChangeToInputMethodManager(false /* hasFocus */); } removeLongPressCallback(); removeTapCallback(); onFocusLost(); - } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { - imm.focusIn(this); + } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { + notifyFocusChangeToInputMethodManager(true /* hasFocus */); } refreshDrawableState(); @@ -17981,10 +17999,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, rebuildOutline(); if (isFocused()) { - InputMethodManager imm = getContext().getSystemService(InputMethodManager.class); - if (imm != null) { - imm.focusIn(this); - } + notifyFocusChangeToInputMethodManager(true /* hasFocus */); } } |