Home | History | Annotate | Download | only in inputmethodservice
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.inputmethodservice;
     18 
     19 import android.annotation.Nullable;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.os.Bundle;
     23 import android.os.IBinder;
     24 import android.os.Looper;
     25 import android.os.ResultReceiver;
     26 import android.view.KeyEvent;
     27 import android.view.MotionEvent;
     28 import android.view.View;
     29 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
     30 import android.view.inputmethod.CompletionInfo;
     31 import android.view.inputmethod.CursorAnchorInfo;
     32 import android.view.inputmethod.EditorInfo;
     33 import android.view.inputmethod.InputConnection;
     34 
     35 import com.android.internal.inputmethod.StartInputFlags;
     36 
     37 /**
     38  * Defines all the public APIs and interfaces that are necessary to implement multi-client IMEs.
     39  *
     40  * <p>Actual implementation is further delegated to
     41  * {@link MultiClientInputMethodServiceDelegateImpl}.</p>
     42  *
     43  * @hide
     44  */
     45 public final class MultiClientInputMethodServiceDelegate {
     46     // @SdkConstant(SdkConstantType.SERVICE_ACTION)
     47     public static final String SERVICE_INTERFACE =
     48             "android.inputmethodservice.MultiClientInputMethodService";
     49 
     50     /**
     51      * Special value that is guaranteed to be not used for IME client ID.
     52      */
     53     public static final int INVALID_CLIENT_ID = -1;
     54 
     55     /**
     56      * Special value that is guaranteed to be not used for window handle.
     57      */
     58     public static final int INVALID_WINDOW_HANDLE = -1;
     59 
     60     private final MultiClientInputMethodServiceDelegateImpl mImpl;
     61 
     62     /**
     63      * Top-level callbacks for this {@link MultiClientInputMethodServiceDelegate}.
     64      */
     65     public interface ServiceCallback {
     66         /**
     67          * Called when this {@link MultiClientInputMethodServiceDelegate} is recognized by the
     68          * system and privileged operations like {@link #createInputMethodWindowToken(int)} are
     69          * ready to be called.
     70          */
     71         void initialized();
     72 
     73         /**
     74          * Called when a new IME client is recognized by the system.
     75          *
     76          * <p>Once the IME receives this callback, the IME can start interacting with the IME client
     77          * by calling {@link #acceptClient(int, ClientCallback, KeyEvent.DispatcherState, Looper)}.
     78          * </p>
     79          *
     80          * @param clientId ID of the client.
     81          * @param uid UID of the IME client.
     82          * @param pid PID of the IME client.
     83          * @param selfReportedDisplayId display ID reported from the IME client. Since the system
     84          *        does not validate this display ID, and at any time the IME client can lose the
     85          *        access to this display ID, the IME needs to call
     86          *        {@link #isUidAllowedOnDisplay(int, int)} to check whether the IME client still
     87          *        has access to this display or not.
     88          */
     89         void addClient(int clientId, int uid, int pid, int selfReportedDisplayId);
     90 
     91         /**
     92          * Called when an IME client is being destroyed.
     93          *
     94          * @param clientId ID of the client.
     95          */
     96         void removeClient(int clientId);
     97     }
     98 
     99     /**
    100      * Per-client callbacks.
    101      */
    102     public interface ClientCallback {
    103         /**
    104          * Called when the associated IME client called {@link
    105          * android.view.inputmethod.InputMethodManager#sendAppPrivateCommand(View, String, Bundle)}.
    106          *
    107          * @param action Name of the command to be performed.
    108          * @param data Any data to include with the command.
    109          * @see android.inputmethodservice.InputMethodService#onAppPrivateCommand(String, Bundle)
    110          */
    111         void onAppPrivateCommand(String action, Bundle data);
    112 
    113         /**
    114          * Called when the associated IME client called {@link
    115          * android.view.inputmethod.InputMethodManager#displayCompletions(View, CompletionInfo[])}.
    116          *
    117          * @param completions Completion information provided from the IME client.
    118          * @see android.inputmethodservice.InputMethodService#onDisplayCompletions(CompletionInfo[])
    119          */
    120         void onDisplayCompletions(CompletionInfo[] completions);
    121 
    122         /**
    123          * Called when this callback session is closed. No further callback should not happen on
    124          * this callback object.
    125          */
    126         void onFinishSession();
    127 
    128         /**
    129          * Called when the associated IME client called {@link
    130          * android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, int)} or
    131          * {@link android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, int,
    132          * ResultReceiver)}.
    133          *
    134          * @param flags The flag passed by the client.
    135          * @param resultReceiver The {@link ResultReceiver} passed by the client.
    136          * @see android.inputmethodservice.InputMethodService#onWindowHidden()
    137          */
    138         void onHideSoftInput(int flags, ResultReceiver resultReceiver);
    139 
    140         /**
    141          * Called when the associated IME client called {@link
    142          * android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} or {@link
    143          * android.view.inputmethod.InputMethodManager#showSoftInput(View, int, ResultReceiver)}.
    144          *
    145          * @param flags The flag passed by the client.
    146          * @param resultReceiver The {@link ResultReceiver} passed by the client.
    147          * @see android.inputmethodservice.InputMethodService#onWindowShown()
    148          */
    149         void onShowSoftInput(int flags, ResultReceiver resultReceiver);
    150 
    151         /**
    152          * A generic callback when {@link InputConnection} is being established.
    153          *
    154          * @param inputConnection The {@link InputConnection} to be established.
    155          * @param editorInfo The {@link EditorInfo} reported from the IME client.
    156          * @param startInputFlags Any combinations of {@link StartInputFlags}.
    157          * @param softInputMode SoftWindowMode specified to this window.
    158          * @param targetWindowHandle A unique Window token.
    159          * @see android.inputmethodservice.InputMethodService#onStartInput(EditorInfo, boolean)
    160          */
    161         void onStartInputOrWindowGainedFocus(
    162                 @Nullable InputConnection inputConnection,
    163                 @Nullable EditorInfo editorInfo,
    164                 @StartInputFlags int startInputFlags,
    165                 @SoftInputModeFlags int softInputMode,
    166                 int targetWindowHandle);
    167 
    168         /**
    169          * Called when the associated IME client called {@link
    170          * android.view.inputmethod.InputMethodManager#toggleSoftInput(int, int)}.
    171          *
    172          * @param showFlags The flag passed by the client.
    173          * @param hideFlags The flag passed by the client.
    174          * @see android.inputmethodservice.InputMethodService#onToggleSoftInput(int, int)
    175          */
    176         void onToggleSoftInput(int showFlags, int hideFlags);
    177 
    178         /**
    179          * Called when the associated IME client called {@link
    180          * android.view.inputmethod.InputMethodManager#updateCursorAnchorInfo(View,
    181          * CursorAnchorInfo)}.
    182          *
    183          * @param info The {@link CursorAnchorInfo} passed by the client.
    184          * @see android.inputmethodservice.InputMethodService#onUpdateCursorAnchorInfo(
    185          *      CursorAnchorInfo)
    186          */
    187         void onUpdateCursorAnchorInfo(CursorAnchorInfo info);
    188 
    189         /**
    190          * Called when the associated IME client called {@link
    191          * android.view.inputmethod.InputMethodManager#updateSelection(View, int, int, int, int)}.
    192          *
    193          * @param oldSelStart The previous selection start index.
    194          * @param oldSelEnd The previous selection end index.
    195          * @param newSelStart The new selection start index.
    196          * @param newSelEnd The new selection end index.
    197          * @param candidatesStart The new candidate start index.
    198          * @param candidatesEnd The new candidate end index.
    199          * @see android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int,
    200          *      int, int)
    201          */
    202         void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd,
    203                 int candidatesStart, int candidatesEnd);
    204 
    205         /**
    206          * Called to give a chance for the IME to intercept generic motion events before they are
    207          * processed by the application.
    208          *
    209          * @param event {@link MotionEvent} that is about to be handled by the IME client.
    210          * @return {@code true} to tell the IME client that the IME handled this event.
    211          * @see android.inputmethodservice.InputMethodService#onGenericMotionEvent(MotionEvent)
    212          */
    213         boolean onGenericMotionEvent(MotionEvent event);
    214 
    215         /**
    216          * Called to give a chance for the IME to intercept key down events before they are
    217          * processed by the application.
    218          *
    219          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
    220          * @param event {@link KeyEvent} for this key down event.
    221          * @return {@code true} to tell the IME client that the IME handled this event.
    222          * @see android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent)
    223          */
    224         boolean onKeyDown(int keyCode, KeyEvent event);
    225 
    226         /**
    227          * Called to give a chance for the IME to intercept key long press events before they are
    228          * processed by the application.
    229          *
    230          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
    231          * @param event {@link KeyEvent} for this key long press event.
    232          * @return {@code true} to tell the IME client that the IME handled this event.
    233          * @see android.inputmethodservice.InputMethodService#onKeyLongPress(int, KeyEvent)
    234          */
    235         boolean onKeyLongPress(int keyCode, KeyEvent event);
    236 
    237         /**
    238          * Called to give a chance for the IME to intercept key multiple events before they are
    239          * processed by the application.
    240          *
    241          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
    242          * @param event {@link KeyEvent} for this key multiple event.
    243          * @return {@code true} to tell the IME client that the IME handled this event.
    244          * @see android.inputmethodservice.InputMethodService#onKeyMultiple(int, int, KeyEvent)
    245          */
    246         boolean onKeyMultiple(int keyCode, KeyEvent event);
    247 
    248         /**
    249          * Called to give a chance for the IME to intercept key up events before they are processed
    250          * by the application.
    251          *
    252          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
    253          * @param event {@link KeyEvent} for this key up event.
    254          * @return {@code true} to tell the IME client that the IME handled this event.
    255          * @see android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent)
    256          */
    257         boolean onKeyUp(int keyCode, KeyEvent event);
    258 
    259         /**
    260          * Called to give a chance for the IME to intercept generic motion events before they are
    261          * processed by the application.
    262          *
    263          * @param event {@link MotionEvent} that is about to be handled by the IME client.
    264          * @return {@code true} to tell the IME client that the IME handled this event.
    265          * @see android.inputmethodservice.InputMethodService#onTrackballEvent(MotionEvent)
    266          */
    267         boolean onTrackballEvent(MotionEvent event);
    268     }
    269 
    270     private MultiClientInputMethodServiceDelegate(Context context,
    271             ServiceCallback serviceCallback) {
    272         mImpl = new MultiClientInputMethodServiceDelegateImpl(context, serviceCallback);
    273     }
    274 
    275     /**
    276      * Must be called by the multi-client IME implementer to create
    277      * {@link MultiClientInputMethodServiceDelegate}.
    278      *
    279      * @param context {@link Context} with which the delegate should interact with the system.
    280      * @param serviceCallback {@link ServiceCallback} to receive service-level callbacks.
    281      * @return A new instance of {@link MultiClientInputMethodServiceDelegate}.
    282      */
    283     public static MultiClientInputMethodServiceDelegate create(Context context,
    284             ServiceCallback serviceCallback) {
    285         return new MultiClientInputMethodServiceDelegate(context, serviceCallback);
    286     }
    287 
    288     /**
    289      * Must be called by the multi-client IME service when {@link android.app.Service#onDestroy()}
    290      * is called.
    291      */
    292     public void onDestroy() {
    293         mImpl.onDestroy();
    294     }
    295 
    296     /**
    297      * Must be called by the multi-client IME service when
    298      * {@link android.app.Service#onBind(Intent)} is called.
    299      *
    300      * @param intent {@link Intent} passed to {@link android.app.Service#onBind(Intent)}.
    301      * @return An {@link IBinder} object that needs to be returned from
    302      *         {@link android.app.Service#onBind(Intent)}.
    303      */
    304     public IBinder onBind(Intent intent) {
    305         return mImpl.onBind(intent);
    306     }
    307 
    308     /**
    309      * Must be called by the multi-client IME service when
    310      * {@link android.app.Service#onUnbind(Intent)} is called.
    311      *
    312      * @param intent {@link Intent} passed to {@link android.app.Service#onUnbind(Intent)}.
    313      * @return A boolean value that needs to be returned from
    314      *         {@link android.app.Service#onUnbind(Intent)}.
    315      */
    316     public boolean onUnbind(Intent intent) {
    317         return mImpl.onUnbind(intent);
    318     }
    319 
    320     /**
    321      * Must be called by the multi-client IME service to create a special window token for IME
    322      * window.
    323      *
    324      * <p>This method is available only after {@link ServiceCallback#initialized()}.</p>
    325      *
    326      * @param displayId display ID on which the IME window will be shown.
    327      * @return Window token to be specified to the IME window/
    328      */
    329     public IBinder createInputMethodWindowToken(int displayId) {
    330         return mImpl.createInputMethodWindowToken(displayId);
    331     }
    332 
    333     /**
    334      * Must be called by the multi-client IME service to notify the system when the IME is ready to
    335      * accept callback events from the specified IME client.
    336      *
    337      * @param clientId The IME client ID specified in
    338      *                 {@link ServiceCallback#addClient(int, int, int, int)}.
    339      * @param clientCallback The {@link ClientCallback} to receive callback events from this IME
    340      *                       client.
    341      * @param dispatcherState {@link KeyEvent.DispatcherState} to be used when receiving key-related
    342      *                        callbacks in {@link ClientCallback}.
    343      * @param looper {@link Looper} on which {@link ClientCallback} will be called back.
    344      */
    345     public void acceptClient(int clientId, ClientCallback clientCallback,
    346             KeyEvent.DispatcherState dispatcherState, Looper looper) {
    347         mImpl.acceptClient(clientId, clientCallback, dispatcherState, looper);
    348     }
    349 
    350     /**
    351      * Must be called by the multi-client IME service to notify the system when the IME is ready to
    352      * interact with the window in the IME client.
    353      *
    354      * @param clientId The IME client ID specified in
    355      *                 {@link ServiceCallback#addClient(int, int, int, int)}.
    356      * @param targetWindowHandle The window handle specified in
    357      *                           {@link ClientCallback#onStartInputOrWindowGainedFocus}.
    358      * @param imeWindowToken The IME window token returned from
    359      *                       {@link #createInputMethodWindowToken(int)}.
    360      */
    361     public void reportImeWindowTarget(int clientId, int targetWindowHandle,
    362             IBinder imeWindowToken) {
    363         mImpl.reportImeWindowTarget(clientId, targetWindowHandle, imeWindowToken);
    364     }
    365 
    366     /**
    367      * Can be called by the multi-client IME service to check if the given {@code uid} is allowed
    368      * to access to {@code displayId}.
    369      *
    370      * @param displayId Display ID to be queried.
    371      * @param uid UID to be queried.
    372      * @return {@code true} if {@code uid} is allowed to access to {@code displayId}.
    373      */
    374     public boolean isUidAllowedOnDisplay(int displayId, int uid) {
    375         return mImpl.isUidAllowedOnDisplay(displayId, uid);
    376     }
    377 
    378     /**
    379      * Can be called by MSIME to activate/deactivate a client when it is gaining/losing focus
    380      * respectively.
    381      *
    382      * @param clientId client ID to activate/deactivate.
    383      * @param active {@code true} to activate a client.
    384      */
    385     public void setActive(int clientId, boolean active) {
    386         mImpl.setActive(clientId, active);
    387     }
    388 }
    389