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.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          */
     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          */
     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          */
     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          */
    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          */
    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          */
    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          */
    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
    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
    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
    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      */
    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      */
    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      */
    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
    198     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
    199     }
    200 
    201     @Override
    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      */
    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      */
    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      */
    246     public void exposeContent(@NonNull InputContentInfo inputContentInfo,
    247             @NonNull InputConnection inputConnection) {
    248         return;
    249     }
    250 
    251 }
    252