• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          */
initialized()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          */
addClient(int clientId, int uid, int pid, int selfReportedDisplayId)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          */
removeClient(int clientId)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          */
onAppPrivateCommand(String action, Bundle data)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          */
onDisplayCompletions(CompletionInfo[] completions)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          */
onFinishSession()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          */
onHideSoftInput(int flags, ResultReceiver resultReceiver)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          */
onShowSoftInput(int flags, ResultReceiver resultReceiver)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          */
onStartInputOrWindowGainedFocus( @ullable InputConnection inputConnection, @Nullable EditorInfo editorInfo, @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int targetWindowHandle)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          */
onToggleSoftInput(int showFlags, int hideFlags)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          */
onUpdateCursorAnchorInfo(CursorAnchorInfo info)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          */
onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd)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          */
onGenericMotionEvent(MotionEvent event)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          */
onKeyDown(int keyCode, KeyEvent event)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          */
onKeyLongPress(int keyCode, KeyEvent event)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          */
onKeyMultiple(int keyCode, KeyEvent event)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          */
onKeyUp(int keyCode, KeyEvent event)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          */
onTrackballEvent(MotionEvent event)267         boolean onTrackballEvent(MotionEvent event);
268     }
269 
MultiClientInputMethodServiceDelegate(Context context, ServiceCallback serviceCallback)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      */
create(Context context, ServiceCallback serviceCallback)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      */
onDestroy()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      */
onBind(Intent intent)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      */
onUnbind(Intent intent)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      */
createInputMethodWindowToken(int displayId)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      */
acceptClient(int clientId, ClientCallback clientCallback, KeyEvent.DispatcherState dispatcherState, Looper looper)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      */
reportImeWindowTarget(int clientId, int targetWindowHandle, IBinder imeWindowToken)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      */
isUidAllowedOnDisplay(int displayId, int uid)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      */
setActive(int clientId, boolean active)385     public void setActive(int clientId, boolean active) {
386         mImpl.setActive(clientId, active);
387     }
388 }
389