• 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#updateCursorAnchorInfo(View,
171          * CursorAnchorInfo)}.
172          *
173          * @param info The {@link CursorAnchorInfo} passed by the client.
174          * @see android.inputmethodservice.InputMethodService#onUpdateCursorAnchorInfo(
175          *      CursorAnchorInfo)
176          */
onUpdateCursorAnchorInfo(CursorAnchorInfo info)177         void onUpdateCursorAnchorInfo(CursorAnchorInfo info);
178 
179         /**
180          * Called when the associated IME client called {@link
181          * android.view.inputmethod.InputMethodManager#updateSelection(View, int, int, int, int)}.
182          *
183          * @param oldSelStart The previous selection start index.
184          * @param oldSelEnd The previous selection end index.
185          * @param newSelStart The new selection start index.
186          * @param newSelEnd The new selection end index.
187          * @param candidatesStart The new candidate start index.
188          * @param candidatesEnd The new candidate end index.
189          * @see android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int,
190          *      int, int)
191          */
onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd)192         void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd,
193                 int candidatesStart, int candidatesEnd);
194 
195         /**
196          * Called to give a chance for the IME to intercept generic motion events before they are
197          * processed by the application.
198          *
199          * @param event {@link MotionEvent} that is about to be handled by the IME client.
200          * @return {@code true} to tell the IME client that the IME handled this event.
201          * @see android.inputmethodservice.InputMethodService#onGenericMotionEvent(MotionEvent)
202          */
onGenericMotionEvent(MotionEvent event)203         boolean onGenericMotionEvent(MotionEvent event);
204 
205         /**
206          * Called to give a chance for the IME to intercept key down events before they are
207          * processed by the application.
208          *
209          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
210          * @param event {@link KeyEvent} for this key down event.
211          * @return {@code true} to tell the IME client that the IME handled this event.
212          * @see android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent)
213          */
onKeyDown(int keyCode, KeyEvent event)214         boolean onKeyDown(int keyCode, KeyEvent event);
215 
216         /**
217          * Called to give a chance for the IME to intercept key long press events before they are
218          * processed by the application.
219          *
220          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
221          * @param event {@link KeyEvent} for this key long press event.
222          * @return {@code true} to tell the IME client that the IME handled this event.
223          * @see android.inputmethodservice.InputMethodService#onKeyLongPress(int, KeyEvent)
224          */
onKeyLongPress(int keyCode, KeyEvent event)225         boolean onKeyLongPress(int keyCode, KeyEvent event);
226 
227         /**
228          * Called to give a chance for the IME to intercept key multiple events before they are
229          * processed by the application.
230          *
231          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
232          * @param event {@link KeyEvent} for this key multiple event.
233          * @return {@code true} to tell the IME client that the IME handled this event.
234          * @see android.inputmethodservice.InputMethodService#onKeyMultiple(int, int, KeyEvent)
235          */
onKeyMultiple(int keyCode, KeyEvent event)236         boolean onKeyMultiple(int keyCode, KeyEvent event);
237 
238         /**
239          * Called to give a chance for the IME to intercept key up events before they are processed
240          * by the application.
241          *
242          * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
243          * @param event {@link KeyEvent} for this key up event.
244          * @return {@code true} to tell the IME client that the IME handled this event.
245          * @see android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent)
246          */
onKeyUp(int keyCode, KeyEvent event)247         boolean onKeyUp(int keyCode, KeyEvent event);
248 
249         /**
250          * Called to give a chance for the IME to intercept generic motion events before they are
251          * processed by the application.
252          *
253          * @param event {@link MotionEvent} that is about to be handled by the IME client.
254          * @return {@code true} to tell the IME client that the IME handled this event.
255          * @see android.inputmethodservice.InputMethodService#onTrackballEvent(MotionEvent)
256          */
onTrackballEvent(MotionEvent event)257         boolean onTrackballEvent(MotionEvent event);
258     }
259 
MultiClientInputMethodServiceDelegate(Context context, ServiceCallback serviceCallback)260     private MultiClientInputMethodServiceDelegate(Context context,
261             ServiceCallback serviceCallback) {
262         mImpl = new MultiClientInputMethodServiceDelegateImpl(context, serviceCallback);
263     }
264 
265     /**
266      * Must be called by the multi-client IME implementer to create
267      * {@link MultiClientInputMethodServiceDelegate}.
268      *
269      * @param context {@link Context} with which the delegate should interact with the system.
270      * @param serviceCallback {@link ServiceCallback} to receive service-level callbacks.
271      * @return A new instance of {@link MultiClientInputMethodServiceDelegate}.
272      */
create(Context context, ServiceCallback serviceCallback)273     public static MultiClientInputMethodServiceDelegate create(Context context,
274             ServiceCallback serviceCallback) {
275         return new MultiClientInputMethodServiceDelegate(context, serviceCallback);
276     }
277 
278     /**
279      * Must be called by the multi-client IME service when {@link android.app.Service#onDestroy()}
280      * is called.
281      */
onDestroy()282     public void onDestroy() {
283         mImpl.onDestroy();
284     }
285 
286     /**
287      * Must be called by the multi-client IME service when
288      * {@link android.app.Service#onBind(Intent)} is called.
289      *
290      * @param intent {@link Intent} passed to {@link android.app.Service#onBind(Intent)}.
291      * @return An {@link IBinder} object that needs to be returned from
292      *         {@link android.app.Service#onBind(Intent)}.
293      */
onBind(Intent intent)294     public IBinder onBind(Intent intent) {
295         return mImpl.onBind(intent);
296     }
297 
298     /**
299      * Must be called by the multi-client IME service when
300      * {@link android.app.Service#onUnbind(Intent)} is called.
301      *
302      * @param intent {@link Intent} passed to {@link android.app.Service#onUnbind(Intent)}.
303      * @return A boolean value that needs to be returned from
304      *         {@link android.app.Service#onUnbind(Intent)}.
305      */
onUnbind(Intent intent)306     public boolean onUnbind(Intent intent) {
307         return mImpl.onUnbind(intent);
308     }
309 
310     /**
311      * Must be called by the multi-client IME service to create a special window token for IME
312      * window.
313      *
314      * <p>This method is available only after {@link ServiceCallback#initialized()}.</p>
315      *
316      * @param displayId display ID on which the IME window will be shown.
317      * @return Window token to be specified to the IME window/
318      */
createInputMethodWindowToken(int displayId)319     public IBinder createInputMethodWindowToken(int displayId) {
320         return mImpl.createInputMethodWindowToken(displayId);
321     }
322 
323     /**
324      * Must be called by the multi-client IME service to notify the system when the IME is ready to
325      * accept callback events from the specified IME client.
326      *
327      * @param clientId The IME client ID specified in
328      *                 {@link ServiceCallback#addClient(int, int, int, int)}.
329      * @param clientCallback The {@link ClientCallback} to receive callback events from this IME
330      *                       client.
331      * @param dispatcherState {@link KeyEvent.DispatcherState} to be used when receiving key-related
332      *                        callbacks in {@link ClientCallback}.
333      * @param looper {@link Looper} on which {@link ClientCallback} will be called back.
334      */
acceptClient(int clientId, ClientCallback clientCallback, KeyEvent.DispatcherState dispatcherState, Looper looper)335     public void acceptClient(int clientId, ClientCallback clientCallback,
336             KeyEvent.DispatcherState dispatcherState, Looper looper) {
337         mImpl.acceptClient(clientId, clientCallback, dispatcherState, looper);
338     }
339 
340     /**
341      * Must be called by the multi-client IME service to notify the system when the IME is ready to
342      * interact with the window in the IME client.
343      *
344      * @param clientId The IME client ID specified in
345      *                 {@link ServiceCallback#addClient(int, int, int, int)}.
346      * @param targetWindowHandle The window handle specified in
347      *                           {@link ClientCallback#onStartInputOrWindowGainedFocus}.
348      * @param imeWindowToken The IME window token returned from
349      *                       {@link #createInputMethodWindowToken(int)}.
350      */
reportImeWindowTarget(int clientId, int targetWindowHandle, IBinder imeWindowToken)351     public void reportImeWindowTarget(int clientId, int targetWindowHandle,
352             IBinder imeWindowToken) {
353         mImpl.reportImeWindowTarget(clientId, targetWindowHandle, imeWindowToken);
354     }
355 
356     /**
357      * Can be called by the multi-client IME service to check if the given {@code uid} is allowed
358      * to access to {@code displayId}.
359      *
360      * @param displayId Display ID to be queried.
361      * @param uid UID to be queried.
362      * @return {@code true} if {@code uid} is allowed to access to {@code displayId}.
363      */
isUidAllowedOnDisplay(int displayId, int uid)364     public boolean isUidAllowedOnDisplay(int displayId, int uid) {
365         return mImpl.isUidAllowedOnDisplay(displayId, uid);
366     }
367 
368     /**
369      * Can be called by MSIME to activate/deactivate a client when it is gaining/losing focus
370      * respectively.
371      *
372      * @param clientId client ID to activate/deactivate.
373      * @param active {@code true} to activate a client.
374      */
setActive(int clientId, boolean active)375     public void setActive(int clientId, boolean active) {
376         mImpl.setActive(clientId, active);
377     }
378 }
379