summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yohei Yukawa <yukawa@google.com> 2018-10-14 19:24:31 +0800
committer Yohei Yukawa <yukawa@google.com> 2018-10-14 19:24:31 +0800
commit4b173140f30c801ab62e0d480d549ee9efa6ca33 (patch)
tree34d9088be9e0725e911f28247f4c5adf506f1018
parent2422220258bf6bba02728581c7948d08c322d67a (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.java45
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 */);
}
}