| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.launcher3.util; |
| |
| import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED; |
| import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; |
| |
| import android.annotation.SuppressLint; |
| import android.app.Activity; |
| import android.content.Context; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.Message; |
| import android.view.View; |
| import android.view.inputmethod.InputMethodManager; |
| |
| import com.android.launcher3.views.ActivityContext; |
| |
| /** |
| * Utility class for offloading some class from UI thread |
| */ |
| public class UiThreadHelper { |
| |
| private static final MainThreadInitializedObject<Handler> HANDLER = |
| new MainThreadInitializedObject<>( |
| 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(); |
| |
| // 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.lookupContext(root.getContext()) |
| .getStatsLogManager() |
| .logger() |
| .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED) |
| ) |
| ); |
| |
| Message mHideKeyboardMsg = Message.obtain(HANDLER.get(root.getContext()), MSG_HIDE_KEYBOARD, |
| token); |
| mHideKeyboardMsg.setData(mHideKeyboardLoggerMsg); |
| mHideKeyboardMsg.sendToTarget(); |
| } |
| |
| public static void setOrientationAsync(Activity activity, int orientation) { |
| Message.obtain(HANDLER.get(activity), MSG_SET_ORIENTATION, orientation, 0, activity) |
| .sendToTarget(); |
| } |
| |
| public static void setBackButtonAlphaAsync(Context context, AsyncCommand command, float alpha, |
| boolean animate) { |
| runAsyncCommand(context, command, Float.floatToIntBits(alpha), animate ? 1 : 0); |
| } |
| |
| public static void runAsyncCommand(Context context, AsyncCommand command, int arg1, int arg2) { |
| Message.obtain(HANDLER.get(context), MSG_RUN_COMMAND, arg1, arg2, command).sendToTarget(); |
| } |
| |
| 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; |
| case MSG_RUN_COMMAND: |
| ((AsyncCommand) message.obj).execute(mContext, message.arg1, message.arg2); |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| public interface AsyncCommand { |
| void execute(Context proxy, int arg1, int arg2); |
| } |
| } |