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