| /* |
| * Copyright (C) 2018 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 android.inputmethodservice; |
| |
| import android.annotation.Nullable; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.os.Bundle; |
| import android.os.IBinder; |
| import android.os.Looper; |
| import android.os.ResultReceiver; |
| import android.view.KeyEvent; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.WindowManager.LayoutParams.SoftInputModeFlags; |
| import android.view.inputmethod.CompletionInfo; |
| import android.view.inputmethod.CursorAnchorInfo; |
| import android.view.inputmethod.EditorInfo; |
| import android.view.inputmethod.InputConnection; |
| |
| import com.android.internal.inputmethod.StartInputFlags; |
| |
| /** |
| * Defines all the public APIs and interfaces that are necessary to implement multi-client IMEs. |
| * |
| * <p>Actual implementation is further delegated to |
| * {@link MultiClientInputMethodServiceDelegateImpl}.</p> |
| * |
| * @hide |
| */ |
| public final class MultiClientInputMethodServiceDelegate { |
| // @SdkConstant(SdkConstantType.SERVICE_ACTION) |
| public static final String SERVICE_INTERFACE = |
| "android.inputmethodservice.MultiClientInputMethodService"; |
| |
| /** |
| * Special value that is guaranteed to be not used for IME client ID. |
| */ |
| public static final int INVALID_CLIENT_ID = -1; |
| |
| /** |
| * Special value that is guaranteed to be not used for window handle. |
| */ |
| public static final int INVALID_WINDOW_HANDLE = -1; |
| |
| private final MultiClientInputMethodServiceDelegateImpl mImpl; |
| |
| /** |
| * Top-level callbacks for this {@link MultiClientInputMethodServiceDelegate}. |
| */ |
| public interface ServiceCallback { |
| /** |
| * Called when this {@link MultiClientInputMethodServiceDelegate} is recognized by the |
| * system and privileged operations like {@link #createInputMethodWindowToken(int)} are |
| * ready to be called. |
| */ |
| void initialized(); |
| |
| /** |
| * Called when a new IME client is recognized by the system. |
| * |
| * <p>Once the IME receives this callback, the IME can start interacting with the IME client |
| * by calling {@link #acceptClient(int, ClientCallback, KeyEvent.DispatcherState, Looper)}. |
| * </p> |
| * |
| * @param clientId ID of the client. |
| * @param uid UID of the IME client. |
| * @param pid PID of the IME client. |
| * @param selfReportedDisplayId display ID reported from the IME client. Since the system |
| * does not validate this display ID, and at any time the IME client can lose the |
| * access to this display ID, the IME needs to call |
| * {@link #isUidAllowedOnDisplay(int, int)} to check whether the IME client still |
| * has access to this display or not. |
| */ |
| void addClient(int clientId, int uid, int pid, int selfReportedDisplayId); |
| |
| /** |
| * Called when an IME client is being destroyed. |
| * |
| * @param clientId ID of the client. |
| */ |
| void removeClient(int clientId); |
| } |
| |
| /** |
| * Per-client callbacks. |
| */ |
| public interface ClientCallback { |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#sendAppPrivateCommand(View, String, Bundle)}. |
| * |
| * @param action Name of the command to be performed. |
| * @param data Any data to include with the command. |
| * @see android.inputmethodservice.InputMethodService#onAppPrivateCommand(String, Bundle) |
| */ |
| void onAppPrivateCommand(String action, Bundle data); |
| |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#displayCompletions(View, CompletionInfo[])}. |
| * |
| * @param completions Completion information provided from the IME client. |
| * @see android.inputmethodservice.InputMethodService#onDisplayCompletions(CompletionInfo[]) |
| */ |
| void onDisplayCompletions(CompletionInfo[] completions); |
| |
| /** |
| * Called when this callback session is closed. No further callback should not happen on |
| * this callback object. |
| */ |
| void onFinishSession(); |
| |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, int)} or |
| * {@link android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, int, |
| * ResultReceiver)}. |
| * |
| * @param flags The flag passed by the client. |
| * @param resultReceiver The {@link ResultReceiver} passed by the client. |
| * @see android.inputmethodservice.InputMethodService#onWindowHidden() |
| */ |
| void onHideSoftInput(int flags, ResultReceiver resultReceiver); |
| |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} or {@link |
| * android.view.inputmethod.InputMethodManager#showSoftInput(View, int, ResultReceiver)}. |
| * |
| * @param flags The flag passed by the client. |
| * @param resultReceiver The {@link ResultReceiver} passed by the client. |
| * @see android.inputmethodservice.InputMethodService#onWindowShown() |
| */ |
| void onShowSoftInput(int flags, ResultReceiver resultReceiver); |
| |
| /** |
| * A generic callback when {@link InputConnection} is being established. |
| * |
| * @param inputConnection The {@link InputConnection} to be established. |
| * @param editorInfo The {@link EditorInfo} reported from the IME client. |
| * @param startInputFlags Any combinations of {@link StartInputFlags}. |
| * @param softInputMode SoftWindowMode specified to this window. |
| * @param targetWindowHandle A unique Window token. |
| * @see android.inputmethodservice.InputMethodService#onStartInput(EditorInfo, boolean) |
| */ |
| void onStartInputOrWindowGainedFocus( |
| @Nullable InputConnection inputConnection, |
| @Nullable EditorInfo editorInfo, |
| @StartInputFlags int startInputFlags, |
| @SoftInputModeFlags int softInputMode, |
| int targetWindowHandle); |
| |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#toggleSoftInput(int, int)}. |
| * |
| * @param showFlags The flag passed by the client. |
| * @param hideFlags The flag passed by the client. |
| * @see android.inputmethodservice.InputMethodService#onToggleSoftInput(int, int) |
| */ |
| void onToggleSoftInput(int showFlags, int hideFlags); |
| |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#updateCursorAnchorInfo(View, |
| * CursorAnchorInfo)}. |
| * |
| * @param info The {@link CursorAnchorInfo} passed by the client. |
| * @see android.inputmethodservice.InputMethodService#onUpdateCursorAnchorInfo( |
| * CursorAnchorInfo) |
| */ |
| void onUpdateCursorAnchorInfo(CursorAnchorInfo info); |
| |
| /** |
| * Called when the associated IME client called {@link |
| * android.view.inputmethod.InputMethodManager#updateSelection(View, int, int, int, int)}. |
| * |
| * @param oldSelStart The previous selection start index. |
| * @param oldSelEnd The previous selection end index. |
| * @param newSelStart The new selection start index. |
| * @param newSelEnd The new selection end index. |
| * @param candidatesStart The new candidate start index. |
| * @param candidatesEnd The new candidate end index. |
| * @see android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, |
| * int, int) |
| */ |
| void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, |
| int candidatesStart, int candidatesEnd); |
| |
| /** |
| * Called to give a chance for the IME to intercept generic motion events before they are |
| * processed by the application. |
| * |
| * @param event {@link MotionEvent} that is about to be handled by the IME client. |
| * @return {@code true} to tell the IME client that the IME handled this event. |
| * @see android.inputmethodservice.InputMethodService#onGenericMotionEvent(MotionEvent) |
| */ |
| boolean onGenericMotionEvent(MotionEvent event); |
| |
| /** |
| * Called to give a chance for the IME to intercept key down events before they are |
| * processed by the application. |
| * |
| * @param keyCode The value in {@link KeyEvent#getKeyCode()}. |
| * @param event {@link KeyEvent} for this key down event. |
| * @return {@code true} to tell the IME client that the IME handled this event. |
| * @see android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent) |
| */ |
| boolean onKeyDown(int keyCode, KeyEvent event); |
| |
| /** |
| * Called to give a chance for the IME to intercept key long press events before they are |
| * processed by the application. |
| * |
| * @param keyCode The value in {@link KeyEvent#getKeyCode()}. |
| * @param event {@link KeyEvent} for this key long press event. |
| * @return {@code true} to tell the IME client that the IME handled this event. |
| * @see android.inputmethodservice.InputMethodService#onKeyLongPress(int, KeyEvent) |
| */ |
| boolean onKeyLongPress(int keyCode, KeyEvent event); |
| |
| /** |
| * Called to give a chance for the IME to intercept key multiple events before they are |
| * processed by the application. |
| * |
| * @param keyCode The value in {@link KeyEvent#getKeyCode()}. |
| * @param event {@link KeyEvent} for this key multiple event. |
| * @return {@code true} to tell the IME client that the IME handled this event. |
| * @see android.inputmethodservice.InputMethodService#onKeyMultiple(int, int, KeyEvent) |
| */ |
| boolean onKeyMultiple(int keyCode, KeyEvent event); |
| |
| /** |
| * Called to give a chance for the IME to intercept key up events before they are processed |
| * by the application. |
| * |
| * @param keyCode The value in {@link KeyEvent#getKeyCode()}. |
| * @param event {@link KeyEvent} for this key up event. |
| * @return {@code true} to tell the IME client that the IME handled this event. |
| * @see android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent) |
| */ |
| boolean onKeyUp(int keyCode, KeyEvent event); |
| |
| /** |
| * Called to give a chance for the IME to intercept generic motion events before they are |
| * processed by the application. |
| * |
| * @param event {@link MotionEvent} that is about to be handled by the IME client. |
| * @return {@code true} to tell the IME client that the IME handled this event. |
| * @see android.inputmethodservice.InputMethodService#onTrackballEvent(MotionEvent) |
| */ |
| boolean onTrackballEvent(MotionEvent event); |
| } |
| |
| private MultiClientInputMethodServiceDelegate(Context context, |
| ServiceCallback serviceCallback) { |
| mImpl = new MultiClientInputMethodServiceDelegateImpl(context, serviceCallback); |
| } |
| |
| /** |
| * Must be called by the multi-client IME implementer to create |
| * {@link MultiClientInputMethodServiceDelegate}. |
| * |
| * @param context {@link Context} with which the delegate should interact with the system. |
| * @param serviceCallback {@link ServiceCallback} to receive service-level callbacks. |
| * @return A new instance of {@link MultiClientInputMethodServiceDelegate}. |
| */ |
| public static MultiClientInputMethodServiceDelegate create(Context context, |
| ServiceCallback serviceCallback) { |
| return new MultiClientInputMethodServiceDelegate(context, serviceCallback); |
| } |
| |
| /** |
| * Must be called by the multi-client IME service when {@link android.app.Service#onDestroy()} |
| * is called. |
| */ |
| public void onDestroy() { |
| mImpl.onDestroy(); |
| } |
| |
| /** |
| * Must be called by the multi-client IME service when |
| * {@link android.app.Service#onBind(Intent)} is called. |
| * |
| * @param intent {@link Intent} passed to {@link android.app.Service#onBind(Intent)}. |
| * @return An {@link IBinder} object that needs to be returned from |
| * {@link android.app.Service#onBind(Intent)}. |
| */ |
| public IBinder onBind(Intent intent) { |
| return mImpl.onBind(intent); |
| } |
| |
| /** |
| * Must be called by the multi-client IME service when |
| * {@link android.app.Service#onUnbind(Intent)} is called. |
| * |
| * @param intent {@link Intent} passed to {@link android.app.Service#onUnbind(Intent)}. |
| * @return A boolean value that needs to be returned from |
| * {@link android.app.Service#onUnbind(Intent)}. |
| */ |
| public boolean onUnbind(Intent intent) { |
| return mImpl.onUnbind(intent); |
| } |
| |
| /** |
| * Must be called by the multi-client IME service to create a special window token for IME |
| * window. |
| * |
| * <p>This method is available only after {@link ServiceCallback#initialized()}.</p> |
| * |
| * @param displayId display ID on which the IME window will be shown. |
| * @return Window token to be specified to the IME window/ |
| */ |
| public IBinder createInputMethodWindowToken(int displayId) { |
| return mImpl.createInputMethodWindowToken(displayId); |
| } |
| |
| /** |
| * Must be called by the multi-client IME service to notify the system when the IME is ready to |
| * accept callback events from the specified IME client. |
| * |
| * @param clientId The IME client ID specified in |
| * {@link ServiceCallback#addClient(int, int, int, int)}. |
| * @param clientCallback The {@link ClientCallback} to receive callback events from this IME |
| * client. |
| * @param dispatcherState {@link KeyEvent.DispatcherState} to be used when receiving key-related |
| * callbacks in {@link ClientCallback}. |
| * @param looper {@link Looper} on which {@link ClientCallback} will be called back. |
| */ |
| public void acceptClient(int clientId, ClientCallback clientCallback, |
| KeyEvent.DispatcherState dispatcherState, Looper looper) { |
| mImpl.acceptClient(clientId, clientCallback, dispatcherState, looper); |
| } |
| |
| /** |
| * Must be called by the multi-client IME service to notify the system when the IME is ready to |
| * interact with the window in the IME client. |
| * |
| * @param clientId The IME client ID specified in |
| * {@link ServiceCallback#addClient(int, int, int, int)}. |
| * @param targetWindowHandle The window handle specified in |
| * {@link ClientCallback#onStartInputOrWindowGainedFocus}. |
| * @param imeWindowToken The IME window token returned from |
| * {@link #createInputMethodWindowToken(int)}. |
| */ |
| public void reportImeWindowTarget(int clientId, int targetWindowHandle, |
| IBinder imeWindowToken) { |
| mImpl.reportImeWindowTarget(clientId, targetWindowHandle, imeWindowToken); |
| } |
| |
| /** |
| * Can be called by the multi-client IME service to check if the given {@code uid} is allowed |
| * to access to {@code displayId}. |
| * |
| * @param displayId Display ID to be queried. |
| * @param uid UID to be queried. |
| * @return {@code true} if {@code uid} is allowed to access to {@code displayId}. |
| */ |
| public boolean isUidAllowedOnDisplay(int displayId, int uid) { |
| return mImpl.isUidAllowedOnDisplay(displayId, uid); |
| } |
| } |