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