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