diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java index 98c71c5bb8..11f2020054 100644 --- a/src/com/android/launcher3/ExtendedEditText.java +++ b/src/com/android/launcher3/ExtendedEditText.java @@ -16,7 +16,6 @@ package com.android.launcher3; import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.SHOW; -import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync; import android.content.Context; import android.text.TextUtils; @@ -90,7 +89,7 @@ public class ExtendedEditText extends EditText { } public void hideKeyboard() { - hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken()); + ActivityContext.lookupContext(getContext()).hideKeyboard(); clearFocus(); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4312c3d647..8f5edb09e1 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -194,7 +194,6 @@ import com.android.launcher3.util.Themes; import com.android.launcher3.util.Thunk; import com.android.launcher3.util.TouchController; import com.android.launcher3.util.TraceHelper; -import com.android.launcher3.util.UiThreadHelper; import com.android.launcher3.util.ViewOnDrawExecutor; import com.android.launcher3.views.ActivityContext; import com.android.launcher3.views.FloatingIconView; @@ -1653,16 +1652,6 @@ public class Launcher extends StatefulActivity } } - /** - * Hides the keyboard if visible - */ - public void hideKeyboard() { - final View v = getWindow().peekDecorView(); - if (v != null && v.getWindowToken() != null) { - UiThreadHelper.hideKeyboardAsync(this, v.getWindowToken()); - } - } - @Override public void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index 31e38903c8..21a7dfbb41 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -21,7 +21,6 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END; import static com.android.launcher3.util.LogConfig.SEARCH_LOGGING; -import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync; import android.content.Context; import android.graphics.Canvas; @@ -162,8 +161,7 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { requestFocus(); mgr.logger().sendToInteractionJankMonitor( LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this); - hideKeyboardAsync(ActivityContext.lookupContext(getContext()), - getApplicationWindowToken()); + ActivityContext.lookupContext(getContext()).hideKeyboard(); break; case SCROLL_STATE_IDLE: mgr.logger().sendToInteractionJankMonitor( diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index f3c5dd6d31..3df1452416 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -17,7 +17,6 @@ package com.android.launcher3.allapps; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB; -import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -503,8 +502,7 @@ public abstract class BaseAllAppsContainerView { @@ -512,8 +510,7 @@ public abstract class BaseAllAppsContainerView( c -> new Handler(UI_HELPER_EXECUTOR.getLooper(), new UiCallbacks(c))); - private static final int MSG_HIDE_KEYBOARD = 1; - private static final int MSG_SET_ORIENTATION = 2; - private static final int MSG_RUN_COMMAND = 3; - private static final String STATS_LOGGER_KEY = "STATS_LOGGER_KEY"; - - @SuppressLint("NewApi") - public static void hideKeyboardAsync(ActivityContext activityContext, IBinder token) { - View root = activityContext.getDragLayer(); - - if (Utilities.ATLEAST_R) { - Preconditions.assertUIThread(); - // Hide keyboard with WindowInsetsController if could. In case - // hideSoftInputFromWindow may get ignored by input connection being finished - // when the screen is off. - // - // In addition, inside IMF, the keyboards are closed asynchronously that launcher no - // longer need to post to the message queue. - final WindowInsetsController wic = root.getWindowInsetsController(); - WindowInsets insets = root.getRootWindowInsets(); - boolean isImeShown = insets != null && insets.isVisible(WindowInsets.Type.ime()); - if (wic != null && isImeShown) { - activityContext.getStatsLogManager().keyboardStateManager().setKeyboardState(HIDE); - // this method cannot be called cross threads - wic.hide(WindowInsets.Type.ime()); - activityContext.getStatsLogManager().logger() - .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED); - return; - } - } - // Since the launcher context cannot be accessed directly from callback, adding secondary - // message to log keyboard close event asynchronously. - Bundle mHideKeyboardLoggerMsg = new Bundle(); - mHideKeyboardLoggerMsg.putParcelable( - STATS_LOGGER_KEY, - Message.obtain( - HANDLER.get(root.getContext()), - () -> activityContext - .getStatsLogManager() - .logger() - .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED) - ) - ); - - Message mHideKeyboardMsg = Message.obtain(HANDLER.get(root.getContext()), MSG_HIDE_KEYBOARD, - token); - mHideKeyboardMsg.setData(mHideKeyboardLoggerMsg); - mHideKeyboardMsg.sendToTarget(); - } + private static final int MSG_SET_ORIENTATION = 1; + private static final int MSG_RUN_COMMAND = 2; public static void setOrientationAsync(Activity activity, int orientation) { Message.obtain(HANDLER.get(activity), MSG_SET_ORIENTATION, orientation, 0, activity) @@ -109,23 +51,14 @@ public class UiThreadHelper { private static class UiCallbacks implements Handler.Callback { private final Context mContext; - private final InputMethodManager mIMM; UiCallbacks(Context context) { mContext = context; - mIMM = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); } @Override public boolean handleMessage(Message message) { switch (message.what) { - case MSG_HIDE_KEYBOARD: - if (mIMM.hideSoftInputFromWindow((IBinder) message.obj, 0)) { - // log keyboard close event only when keyboard is actually closed - ((Message) message.getData().getParcelable(STATS_LOGGER_KEY)) - .sendToTarget(); - } - return true; case MSG_SET_ORIENTATION: ((Activity) message.obj).setRequestedOrientation(message.arg1); return true; diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index e2dc34fb67..dd5b22eb84 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -15,16 +15,26 @@ */ package com.android.launcher3.views; +import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.HIDE; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED; +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; + import android.content.Context; import android.content.ContextWrapper; import android.graphics.Rect; +import android.os.IBinder; import android.view.LayoutInflater; import android.view.View; import android.view.View.AccessibilityDelegate; +import android.view.WindowInsets; +import android.view.WindowInsetsController; +import android.view.inputmethod.InputMethodManager; import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Utilities; import com.android.launcher3.allapps.ActivityAllAppsContainerView; import com.android.launcher3.allapps.search.SearchAdapterProvider; import com.android.launcher3.dot.DotInfo; @@ -36,6 +46,7 @@ import com.android.launcher3.model.StringCache; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.util.OnboardingPrefs; +import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.ViewCache; /** @@ -202,4 +213,47 @@ public interface ActivityContext { ActivityAllAppsContainerView appsView) { return null; } + + /** + * Hides the keyboard if it is visible + */ + default void hideKeyboard() { + View root = getDragLayer(); + if (root == null) { + return; + } + if (Utilities.ATLEAST_R) { + Preconditions.assertUIThread(); + // Hide keyboard with WindowInsetsController if could. In case + // hideSoftInputFromWindow may get ignored by input connection being finished + // when the screen is off. + // + // In addition, inside IMF, the keyboards are closed asynchronously that launcher no + // longer need to post to the message queue. + final WindowInsetsController wic = root.getWindowInsetsController(); + WindowInsets insets = root.getRootWindowInsets(); + boolean isImeShown = insets != null && insets.isVisible(WindowInsets.Type.ime()); + if (wic != null && isImeShown) { + StatsLogManager slm = getStatsLogManager(); + slm.keyboardStateManager().setKeyboardState(HIDE); + + // this method cannot be called cross threads + wic.hide(WindowInsets.Type.ime()); + slm.logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED); + return; + } + } + + InputMethodManager imm = root.getContext().getSystemService(InputMethodManager.class); + IBinder token = root.getWindowToken(); + if (imm != null && token != null) { + UI_HELPER_EXECUTOR.execute(() -> { + if (imm.hideSoftInputFromWindow(token, 0)) { + // log keyboard close event only when keyboard is actually closed + MAIN_EXECUTOR.execute(() -> + getStatsLogManager().logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)); + } + }); + } + } } diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java index 6e6512d294..40e4ce1c04 100644 --- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java +++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java @@ -20,8 +20,6 @@ import static android.view.HapticFeedbackConstants.CLOCK_TICK; import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE; -import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync; - import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.Resources; @@ -313,7 +311,7 @@ public class RecyclerViewFastScroller extends View { } private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) { - hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken()); + ActivityContext.lookupContext(getContext()).hideKeyboard(); mIsDragging = true; if (mCanThumbDetach) { mIsThumbDetached = true;