1 /*
2  * Copyright (C) 2007-2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package android.view.inputmethod;
18 
19 import android.annotation.DurationMillisLong;
20 import android.annotation.IntDef;
21 import android.annotation.MainThread;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SdkConstant;
25 import android.annotation.SdkConstant.SdkConstantType;
26 import android.inputmethodservice.InputMethodService;
27 import android.os.IBinder;
28 import android.os.RemoteException;
29 import android.os.ResultReceiver;
30 import android.util.Log;
31 import android.view.InputChannel;
32 import android.view.MotionEvent;
33 import android.view.View;
34 
35 import com.android.internal.inputmethod.IInlineSuggestionsRequestCallback;
36 import com.android.internal.inputmethod.IInputMethod;
37 import com.android.internal.inputmethod.InlineSuggestionsRequestInfo;
38 import com.android.internal.inputmethod.InputMethodNavButtonFlags;
39 
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
42 import java.util.List;
43 
44 /**
45  * The InputMethod interface represents an input method which can generate key
46  * events and text, such as digital, email addresses, CJK characters, other
47  * language characters, and etc., while handling various input events, and send
48  * the text back to the application that requests text input.  See
49  * {@link InputMethodManager} for more general information about the
50  * architecture.
51  *
52  * <p>Applications will not normally use this interface themselves, instead
53  * relying on the standard interaction provided by
54  * {@link android.widget.TextView} and {@link android.widget.EditText}.
55  *
56  * <p>Those implementing input methods should normally do so by deriving from
57  * {@link InputMethodService} or one of its subclasses.  When implementing
58  * an input method, the service component containing it must also supply
59  * a {@link #SERVICE_META_DATA} meta-data field, referencing an XML resource
60  * providing details about the input method.  All input methods also must
61  * require that clients hold the
62  * {@link android.Manifest.permission#BIND_INPUT_METHOD} in order to interact
63  * with the service; if this is not required, the system will not use that
64  * input method, because it can not trust that it is not compromised.
65  *
66  * <p>The InputMethod interface is actually split into two parts: the interface
67  * here is the top-level interface to the input method, providing all
68  * access to it, which only the system can access (due to the BIND_INPUT_METHOD
69  * permission requirement).  In addition its method
70  * {@link #createSession(android.view.inputmethod.InputMethod.SessionCallback)}
71  * can be called to instantate a secondary {@link InputMethodSession} interface
72  * which is what clients use to communicate with the input method.
73  */
74 public interface InputMethod {
75     /** @hide **/
76     public static final String TAG = "InputMethod";
77     /**
78      * This is the interface name that a service implementing an input
79      * method should say that it supports -- that is, this is the action it
80      * uses for its intent filter.
81      * To be supported, the service must also require the
82      * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission so
83      * that other applications can not abuse it.
84      */
85     @SdkConstant(SdkConstantType.SERVICE_ACTION)
86     public static final String SERVICE_INTERFACE = "android.view.InputMethod";
87 
88     /**
89      * Name under which an InputMethod service component publishes information
90      * about itself.  This meta-data must reference an XML resource containing
91      * an
92      * <code>&lt;{@link android.R.styleable#InputMethod input-method}&gt;</code>
93      * tag.
94      */
95     public static final String SERVICE_META_DATA = "android.view.im";
96 
97     public interface SessionCallback {
sessionCreated(InputMethodSession session)98         public void sessionCreated(InputMethodSession session);
99     }
100 
101     /**
102      * Called first thing after an input method is created, this supplies a
103      * unique token for the session it has with the system service as well as
104      * IPC endpoint to do some other privileged operations.
105      *
106      * @param params Contains parameters to initialize the {@link InputMethodService}.
107      * @hide
108      */
109     @MainThread
initializeInternal(@onNull IInputMethod.InitParams params)110     default void initializeInternal(@NonNull IInputMethod.InitParams params) {
111         attachToken(params.token);
112     }
113 
114     /**
115      * Called to notify the IME that Autofill Frameworks requested an inline suggestions request.
116      *
117      * @param requestInfo information needed to create an {@link InlineSuggestionsRequest}.
118      * @param cb {@link IInlineSuggestionsRequestCallback} used to pass back the request object.
119      *
120      * @hide
121      */
onCreateInlineSuggestionsRequest(InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb)122     default void onCreateInlineSuggestionsRequest(InlineSuggestionsRequestInfo requestInfo,
123             IInlineSuggestionsRequestCallback cb) {
124         try {
125             cb.onInlineSuggestionsUnsupported();
126         } catch (RemoteException e) {
127             Log.w(TAG, "Failed to call onInlineSuggestionsUnsupported.", e);
128         }
129     }
130 
131     /**
132      * Called first thing after an input method is created, this supplies a
133      * unique token for the session it has with the system service.  It is
134      * needed to identify itself with the service to validate its operations.
135      * This token <strong>must not</strong> be passed to applications, since
136      * it grants special priviledges that should not be given to applications.
137      *
138      * <p>The system guarantees that this method is called back between
139      * {@link InputMethodService#onCreate()} and {@link InputMethodService#onDestroy()}
140      * at most once.
141      */
142     @MainThread
attachToken(IBinder token)143     public void attachToken(IBinder token);
144 
145     /**
146      * Bind a new application environment in to the input method, so that it
147      * can later start and stop input processing.
148      * Typically this method is called when this input method is enabled in an
149      * application for the first time.
150      *
151      * @param binding Information about the application window that is binding
152      * to the input method.
153      *
154      * @see InputBinding
155      * @see #unbindInput()
156      */
157     @MainThread
bindInput(InputBinding binding)158     public void bindInput(InputBinding binding);
159 
160     /**
161      * Unbind an application environment, called when the information previously
162      * set by {@link #bindInput} is no longer valid for this input method.
163      *
164      * <p>
165      * Typically this method is called when the application changes to be
166      * non-foreground.
167      */
168     @MainThread
unbindInput()169     public void unbindInput();
170 
171     /**
172      * This method is called when the application starts to receive text and it
173      * is ready for this input method to process received events and send result
174      * text back to the application.
175      *
176      * @param inputConnection Optional specific input connection for
177      * communicating with the text box; if null, you should use the generic
178      * bound input connection.
179      * @param editorInfo Information about the text box (typically, an EditText)
180      *        that requests input.
181      *
182      * @see EditorInfo
183      */
184     @MainThread
startInput(InputConnection inputConnection, EditorInfo editorInfo)185     public void startInput(InputConnection inputConnection, EditorInfo editorInfo);
186 
187     /**
188      * This method is called when the state of this input method needs to be
189      * reset.
190      *
191      * <p>
192      * Typically, this method is called when the input focus is moved from one
193      * text box to another.
194      *
195      * @param inputConnection Optional specific input connection for
196      * communicating with the text box; if null, you should use the generic
197      * bound input connection.
198      * @param editorInfo The attribute of the text box (typically, a EditText)
199      *        that requests input.
200      *
201      * @see EditorInfo
202      */
203     @MainThread
restartInput(InputConnection inputConnection, EditorInfo editorInfo)204     public void restartInput(InputConnection inputConnection, EditorInfo editorInfo);
205 
206     /**
207      * This method is called when {@link #startInput(InputConnection, EditorInfo)} or
208      * {@link #restartInput(InputConnection, EditorInfo)} needs to be dispatched.
209      *
210      * <p>Note: This method is hidden because {@link IInputMethod.StartInputParams} is an internal
211      * details, which should not be exposed to the IME developers. If you override this method, you
212      * are responsible for not breaking existing IMEs that expect
213      * {@link #startInput(InputConnection, EditorInfo)} to be still called back.</p>
214      *
215      * @param inputConnection optional specific input connection for communicating with the text
216      *                        box; if {@code null}, you should use the generic bound input
217      *                        connection
218      * @param params Raw object of {@link IInputMethod.StartInputParams}.
219      * @see #startInput(InputConnection, EditorInfo)
220      * @see #restartInput(InputConnection, EditorInfo)
221      * @see EditorInfo
222      * @hide
223      */
224     @MainThread
dispatchStartInput(@ullable InputConnection inputConnection, @NonNull IInputMethod.StartInputParams params)225     default void dispatchStartInput(@Nullable InputConnection inputConnection,
226             @NonNull IInputMethod.StartInputParams params) {
227         if (params.restarting) {
228             restartInput(inputConnection, params.editorInfo);
229         } else {
230             startInput(inputConnection, params.editorInfo);
231         }
232     }
233 
234     /**
235      * Notifies that {@link InputMethodNavButtonFlags} have been updated.
236      *
237      * @param navButtonFlags The new {@link InputMethodNavButtonFlags}.
238      * @hide
239      */
240     @MainThread
onNavButtonFlagsChanged(@nputMethodNavButtonFlags int navButtonFlags)241     default void onNavButtonFlagsChanged(@InputMethodNavButtonFlags int navButtonFlags) {
242     }
243 
244     /**
245      * Create a new {@link InputMethodSession} that can be handed to client
246      * applications for interacting with the input method.  You can later
247      * use {@link #revokeSession(InputMethodSession)} to destroy the session
248      * so that it can no longer be used by any clients.
249      *
250      * @param callback Interface that is called with the newly created session.
251      */
252     @MainThread
createSession(SessionCallback callback)253     public void createSession(SessionCallback callback);
254 
255     /**
256      * Control whether a particular input method session is active.
257      *
258      * @param session The {@link InputMethodSession} previously provided through
259      * SessionCallback.sessionCreated() that is to be changed.
260      */
261     @MainThread
setSessionEnabled(InputMethodSession session, boolean enabled)262     public void setSessionEnabled(InputMethodSession session, boolean enabled);
263 
264     /**
265      * Disable and destroy a session that was previously created with
266      * {@link #createSession(android.view.inputmethod.InputMethod.SessionCallback)}.
267      * After this call, the given session interface is no longer active and
268      * calls on it will fail.
269      *
270      * @param session The {@link InputMethodSession} previously provided through
271      * SessionCallback.sessionCreated() that is to be revoked.
272      */
273     @MainThread
revokeSession(InputMethodSession session)274     public void revokeSession(InputMethodSession session);
275 
276     /** @hide */
277     @IntDef(flag = true, prefix = { "SHOW_" }, value = {
278             SHOW_EXPLICIT,
279             SHOW_FORCED,
280     })
281     @Retention(RetentionPolicy.SOURCE)
282     @interface ShowFlags {}
283 
284     /**
285      * Flag for {@link #showSoftInput}: this show has been explicitly
286      * requested by the user.  If not set, the system has decided it may be
287      * a good idea to show the input method based on a navigation operation
288      * in the UI.
289      */
290     public static final int SHOW_EXPLICIT = 0x00001;
291 
292     /**
293      * Flag for {@link #showSoftInput}: this show has been forced to
294      * happen by the user.  If set, the input method should remain visible
295      * until deliberated dismissed by the user in its UI.
296      */
297     public static final int SHOW_FORCED = 0x00002;
298 
299     /**
300      * Request that any soft input part of the input method be shown to the user.
301      *
302      * @param resultReceiver The client requesting the show may wish to
303      * be told the impact of their request, which should be supplied here.
304      * The result code should be
305      * {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
306      * {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN InputMethodManager.RESULT_UNCHANGED_HIDDEN},
307      * {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
308      * {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
309      * @param showInputToken an opaque {@link android.os.Binder} token to identify which API call
310      *        of {@link InputMethodManager#showSoftInput(View, int)} is associated with
311      *        this callback.
312      * @param statsToken the token tracking the current IME show request or {@code null} otherwise.
313      * @hide
314      */
315     @MainThread
showSoftInputWithToken(@howFlags int flags, ResultReceiver resultReceiver, IBinder showInputToken, @Nullable ImeTracker.Token statsToken)316     public default void showSoftInputWithToken(@ShowFlags int flags, ResultReceiver resultReceiver,
317             IBinder showInputToken, @Nullable ImeTracker.Token statsToken) {
318         showSoftInput(flags, resultReceiver);
319     }
320 
321     /**
322      * Request that any soft input part of the input method be shown to the user.
323      *
324      * @param resultReceiver The client requesting the show may wish to
325      * be told the impact of their request, which should be supplied here.
326      * The result code should be
327      * {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
328      * {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN InputMethodManager.RESULT_UNCHANGED_HIDDEN},
329      * {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
330      * {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
331      */
332     @MainThread
showSoftInput(@howFlags int flags, ResultReceiver resultReceiver)333     public void showSoftInput(@ShowFlags int flags, ResultReceiver resultReceiver);
334 
335     /**
336      * Request that any soft input part of the input method be hidden from the user.
337      *
338      * @param flags Provides additional information about the hide request.
339      * Currently always 0.
340      * @param resultReceiver The client requesting the show may wish to
341      * be told the impact of their request, which should be supplied here.
342      * The result code should be
343      * {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
344      * {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN InputMethodManager.RESULT_UNCHANGED_HIDDEN},
345      * {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
346      * {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
347      * @param hideInputToken an opaque {@link android.os.Binder} token to identify which API call
348      *         of {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}} is associated
349      *         with this callback.
350      * @param statsToken the token tracking the current IME hide request or {@code null} otherwise.
351      * @hide
352      */
353     @MainThread
hideSoftInputWithToken(int flags, ResultReceiver resultReceiver, IBinder hideInputToken, @Nullable ImeTracker.Token statsToken)354     public default void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver,
355             IBinder hideInputToken, @Nullable ImeTracker.Token statsToken) {
356         hideSoftInput(flags, resultReceiver);
357     }
358 
359     /**
360      * Request that any soft input part of the input method be hidden from the user.
361      *
362      * @param flags Provides additional information about the hide request.
363      * Currently always 0.
364      * @param resultReceiver The client requesting the show may wish to
365      * be told the impact of their request, which should be supplied here.
366      * The result code should be
367      * {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
368      * {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN
369      *        InputMethodManager.RESULT_UNCHANGED_HIDDEN},
370      * {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
371      * {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
372      */
373     @MainThread
hideSoftInput(int flags, ResultReceiver resultReceiver)374     public void hideSoftInput(int flags, ResultReceiver resultReceiver);
375 
376     /**
377      * Notify that the input method subtype is being changed in the same input method.
378      * @param subtype New subtype of the notified input method
379      */
380     @MainThread
changeInputMethodSubtype(InputMethodSubtype subtype)381     public void changeInputMethodSubtype(InputMethodSubtype subtype);
382 
383     /**
384      * Checks if IME is ready to start stylus handwriting session.
385      * If yes, {@link #startStylusHandwriting(int, InputChannel, List)} is called.
386      * @param requestId
387      * @hide
388      */
canStartStylusHandwriting(int requestId)389     default void canStartStylusHandwriting(int requestId) {
390         // intentionally empty
391     }
392 
393     /**
394      * This method is called when the user tapped or clicked an {@link android.widget.Editor}.
395      * @param toolType {@link android.view.MotionEvent#getToolType(int)} used for clicking editor.
396      * @hide
397      */
updateEditorToolType(int toolType)398     default void updateEditorToolType(int toolType) {
399         // intentionally empty
400     }
401 
402     /**
403      * Start stylus handwriting session.
404      * @hide
405      */
startStylusHandwriting( int requestId, @NonNull InputChannel channel, @Nullable List<MotionEvent> events)406     default void startStylusHandwriting(
407             int requestId, @NonNull InputChannel channel, @Nullable List<MotionEvent> events) {
408         // intentionally empty
409     }
410 
411     /**
412      * Initialize Ink window early-on.
413      * @hide
414      */
initInkWindow()415     default void initInkWindow() {
416         // intentionally empty
417     }
418 
419     /**
420      * Finish stylus handwriting session.
421      * @hide
422      */
finishStylusHandwriting()423     default void finishStylusHandwriting() {
424         // intentionally empty
425     }
426 
427     /**
428      * Remove stylus handwriting window.
429      * @hide
430      */
removeStylusHandwritingWindow()431     default void removeStylusHandwritingWindow() {
432         // intentionally empty
433     }
434 
435     /**
436      * Set a stylus idle-timeout after which handwriting {@code InkWindow} will be removed.
437      * @hide
438      */
setStylusWindowIdleTimeoutForTest(@urationMillisLong long timeout)439     default void setStylusWindowIdleTimeoutForTest(@DurationMillisLong long timeout) {
440         // intentionally empty
441     }
442 }
443