• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.inputmethodservice;
18 
19 import android.annotation.MainThread;
20 import android.annotation.NonNull;
21 import android.app.Service;
22 import android.content.Intent;
23 import android.os.IBinder;
24 import android.util.proto.ProtoOutputStream;
25 import android.view.KeyEvent;
26 import android.view.MotionEvent;
27 import android.view.inputmethod.InputConnection;
28 import android.view.inputmethod.InputContentInfo;
29 import android.view.inputmethod.InputMethod;
30 import android.view.inputmethod.InputMethodSession;
31 
32 import java.io.FileDescriptor;
33 import java.io.PrintWriter;
34 
35 /**
36  * AbstractInputMethodService provides a abstract base class for input methods.
37  * Normal input method implementations will not derive from this directly,
38  * instead building on top of {@link InputMethodService} or another more
39  * complete base class.  Be sure to read {@link InputMethod} for more
40  * information on the basics of writing input methods.
41  *
42  * <p>This class combines a Service (representing the input method component
43  * to the system with the InputMethod interface that input methods must
44  * implement.  This base class takes care of reporting your InputMethod from
45  * the service when clients bind to it, but provides no standard implementation
46  * of the InputMethod interface itself.  Derived classes must implement that
47  * interface.
48  */
49 public abstract class AbstractInputMethodService extends Service
50         implements KeyEvent.Callback {
51     private InputMethod mInputMethod;
52 
53     final KeyEvent.DispatcherState mDispatcherState
54             = new KeyEvent.DispatcherState();
55 
56     /**
57      * Base class for derived classes to implement their {@link InputMethod}
58      * interface.  This takes care of basic maintenance of the input method,
59      * but most behavior must be implemented in a derived class.
60      */
61     public abstract class AbstractInputMethodImpl implements InputMethod {
62         /**
63          * Instantiate a new client session for the input method, by calling
64          * back to {@link AbstractInputMethodService#onCreateInputMethodSessionInterface()
65          * AbstractInputMethodService.onCreateInputMethodSessionInterface()}.
66          */
67         @MainThread
createSession(SessionCallback callback)68         public void createSession(SessionCallback callback) {
69             callback.sessionCreated(onCreateInputMethodSessionInterface());
70         }
71 
72         /**
73          * Take care of enabling or disabling an existing session by calling its
74          * {@link AbstractInputMethodSessionImpl#revokeSelf()
75          * AbstractInputMethodSessionImpl.setEnabled()} method.
76          */
77         @MainThread
setSessionEnabled(InputMethodSession session, boolean enabled)78         public void setSessionEnabled(InputMethodSession session, boolean enabled) {
79             ((AbstractInputMethodSessionImpl)session).setEnabled(enabled);
80         }
81 
82         /**
83          * Take care of killing an existing session by calling its
84          * {@link AbstractInputMethodSessionImpl#revokeSelf()
85          * AbstractInputMethodSessionImpl.revokeSelf()} method.
86          */
87         @MainThread
revokeSession(InputMethodSession session)88         public void revokeSession(InputMethodSession session) {
89             ((AbstractInputMethodSessionImpl)session).revokeSelf();
90         }
91     }
92 
93     /**
94      * Base class for derived classes to implement their {@link InputMethodSession}
95      * interface.  This takes care of basic maintenance of the session,
96      * but most behavior must be implemented in a derived class.
97      */
98     public abstract class AbstractInputMethodSessionImpl implements InputMethodSession {
99         boolean mEnabled = true;
100         boolean mRevoked;
101 
102         /**
103          * Check whether this session has been enabled by the system.  If not
104          * enabled, you should not execute any calls on to it.
105          */
isEnabled()106         public boolean isEnabled() {
107             return mEnabled;
108         }
109 
110         /**
111          * Check whether this session has been revoked by the system.  Revoked
112          * session is also always disabled, so there is generally no need to
113          * explicitly check for this.
114          */
isRevoked()115         public boolean isRevoked() {
116             return mRevoked;
117         }
118 
119         /**
120          * Change the enabled state of the session.  This only works if the
121          * session has not been revoked.
122          */
setEnabled(boolean enabled)123         public void setEnabled(boolean enabled) {
124             if (!mRevoked) {
125                 mEnabled = enabled;
126             }
127         }
128 
129         /**
130          * Revoke the session from the client.  This disabled the session, and
131          * prevents it from ever being enabled again.
132          */
revokeSelf()133         public void revokeSelf() {
134             mRevoked = true;
135             mEnabled = false;
136         }
137 
138         /**
139          * Take care of dispatching incoming key events to the appropriate
140          * callbacks on the service, and tell the client when this is done.
141          */
142         @Override
dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback)143         public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback) {
144             boolean handled = event.dispatch(AbstractInputMethodService.this,
145                     mDispatcherState, this);
146             if (callback != null) {
147                 callback.finishedEvent(seq, handled);
148             }
149         }
150 
151         /**
152          * Take care of dispatching incoming trackball events to the appropriate
153          * callbacks on the service, and tell the client when this is done.
154          */
155         @Override
dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback)156         public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback) {
157             boolean handled = onTrackballEvent(event);
158             if (callback != null) {
159                 callback.finishedEvent(seq, handled);
160             }
161         }
162 
163         /**
164          * Take care of dispatching incoming generic motion events to the appropriate
165          * callbacks on the service, and tell the client when this is done.
166          */
167         @Override
dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback)168         public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) {
169             boolean handled = onGenericMotionEvent(event);
170             if (callback != null) {
171                 callback.finishedEvent(seq, handled);
172             }
173         }
174     }
175 
176     /**
177      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
178      * for used for processing events from the target application.
179      * Normally you will not need to use this directly, but
180      * just use the standard high-level event callbacks like {@link #onKeyDown}.
181      */
getKeyDispatcherState()182     public KeyEvent.DispatcherState getKeyDispatcherState() {
183         return mDispatcherState;
184     }
185 
186     /**
187      * Called by the framework during initialization, when the InputMethod
188      * interface for this service needs to be created.
189      */
onCreateInputMethodInterface()190     public abstract AbstractInputMethodImpl onCreateInputMethodInterface();
191 
192     /**
193      * Called by the framework when a new InputMethodSession interface is
194      * needed for a new client of the input method.
195      */
onCreateInputMethodSessionInterface()196     public abstract AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
197 
198     /**
199      * Dumps the internal state of IME to a protocol buffer output stream.
200      *
201      * @param proto ProtoOutputStream to dump data to.
202      * @param icProto {@link InputConnection} call data in proto format.
203      * @hide
204      */
205     @SuppressWarnings("HiddenAbstractMethod")
dumpProtoInternal(ProtoOutputStream proto, ProtoOutputStream icProto)206     public abstract void dumpProtoInternal(ProtoOutputStream proto, ProtoOutputStream icProto);
207 
208     /**
209      * Implement this to handle {@link android.os.Binder#dump Binder.dump()}
210      * calls on your input method.
211      */
212     @Override
dump(FileDescriptor fd, PrintWriter fout, String[] args)213     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
214     }
215 
216     @Override
onBind(Intent intent)217     final public IBinder onBind(Intent intent) {
218         if (mInputMethod == null) {
219             mInputMethod = onCreateInputMethodInterface();
220         }
221         return new IInputMethodWrapper(this, mInputMethod);
222     }
223 
224     /**
225      * Implement this to handle trackball events on your input method.
226      *
227      * @param event The motion event being received.
228      * @return True if the event was handled in this function, false otherwise.
229      * @see android.view.View#onTrackballEvent(MotionEvent)
230      */
onTrackballEvent(MotionEvent event)231     public boolean onTrackballEvent(MotionEvent event) {
232         return false;
233     }
234 
235     /**
236      * Implement this to handle generic motion events on your input method.
237      *
238      * @param event The motion event being received.
239      * @return True if the event was handled in this function, false otherwise.
240      * @see android.view.View#onGenericMotionEvent(MotionEvent)
241      */
onGenericMotionEvent(MotionEvent event)242     public boolean onGenericMotionEvent(MotionEvent event) {
243         return false;
244     }
245 
246     /**
247      * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
248      * permission to the content.
249      *
250      * <p>Default implementation does nothing.</p>
251      *
252      * @param inputContentInfo Content to be temporarily exposed from the input method to the
253      * application.
254      * This cannot be {@code null}.
255      * @param inputConnection {@link InputConnection} with which
256      * {@link InputConnection#commitContent(InputContentInfo, int, android.os.Bundle)} will be
257      * called.
258      * @return {@code false} if we cannot allow a temporary access permission.
259      * @hide
260      */
exposeContent(@onNull InputContentInfo inputContentInfo, @NonNull InputConnection inputConnection)261     public void exposeContent(@NonNull InputContentInfo inputContentInfo,
262             @NonNull InputConnection inputConnection) {
263         return;
264     }
265 
266     /**
267      * Called when the user took some actions that should be taken into consideration to update the
268      * MRU list for input method rotation.
269      *
270      * @hide
271      */
notifyUserActionIfNecessary()272     public void notifyUserActionIfNecessary() {
273     }
274 
275     /** @hide */
276     @Override
isUiContext()277     public final boolean isUiContext() {
278         return true;
279     }
280 }
281