Home | History | Annotate | Download | only in view
      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 com.android.internal.view;
     18 
     19 import static java.lang.annotation.RetentionPolicy.SOURCE;
     20 
     21 import android.annotation.IntDef;
     22 import android.content.ComponentName;
     23 import android.content.Intent;
     24 import android.content.ServiceConnection;
     25 import android.os.IBinder;
     26 import android.os.Parcel;
     27 import android.os.Parcelable;
     28 import android.os.UserHandle;
     29 import android.view.InputChannel;
     30 
     31 import java.lang.annotation.Retention;
     32 
     33 /**
     34  * Bundle of information returned by input method manager about a successful
     35  * binding to an input method.
     36  */
     37 public final class InputBindResult implements Parcelable {
     38 
     39     @Retention(SOURCE)
     40     @IntDef({
     41             ResultCode.SUCCESS_WITH_IME_SESSION,
     42             ResultCode.SUCCESS_WAITING_IME_SESSION,
     43             ResultCode.SUCCESS_WAITING_IME_BINDING,
     44             ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
     45             ResultCode.ERROR_NULL,
     46             ResultCode.ERROR_NO_IME,
     47             ResultCode.ERROR_INVALID_PACKAGE_NAME,
     48             ResultCode.ERROR_SYSTEM_NOT_READY,
     49             ResultCode.ERROR_IME_NOT_CONNECTED,
     50             ResultCode.ERROR_INVALID_USER,
     51             ResultCode.ERROR_NULL_EDITOR_INFO,
     52             ResultCode.ERROR_NOT_IME_TARGET_WINDOW,
     53     })
     54     public @interface ResultCode {
     55         /**
     56          * Indicates that everything in this result object including {@link #method} is valid.
     57          */
     58         int SUCCESS_WITH_IME_SESSION = 0;
     59         /**
     60          * Indicates that this is a temporary binding until the
     61          * {@link android.inputmethodservice.InputMethodService} (IMS) establishes a valid session
     62          * to {@link com.android.server.InputMethodManagerService} (IMMS).
     63          *
     64          * <p>Note that in this state the IMS is already bound to IMMS but the logical session
     65          * is not yet established on top of the IPC channel.</p>
     66          *
     67          * <p>Some of fields such as {@link #channel} is not yet available.</p>
     68          *
     69          * @see android.inputmethodservice.InputMethodService##onCreateInputMethodSessionInterface()
     70          **/
     71         int SUCCESS_WAITING_IME_SESSION = 1;
     72         /**
     73          * Indicates that this is a temporary binding until the
     74          * {@link android.inputmethodservice.InputMethodService} (IMS) establishes a valid session
     75          * to {@link com.android.server.InputMethodManagerService} (IMMS).
     76          *
     77          * <p>Note that in this state the IMMS has already initiated a connection to the IMS but
     78          * the binding process is not completed yet.</p>
     79          *
     80          * <p>Some of fields such as {@link #channel} is not yet available.</p>
     81          * @see android.content.ServiceConnection#onServiceConnected(ComponentName, IBinder)
     82          */
     83         int SUCCESS_WAITING_IME_BINDING = 2;
     84         /**
     85          * Indicates that this is not intended for starting input but just for reporting window
     86          * focus change from the application process.
     87          *
     88          * <p>All other fields do not have meaningful value.</p>
     89          */
     90         int SUCCESS_REPORT_WINDOW_FOCUS_ONLY = 3;
     91         /**
     92          * Indicates somehow
     93          * {@link com.android.server.InputMethodManagerService#startInputOrWindowGainedFocus} is
     94          * trying to return null {@link InputBindResult}, which must never happen.
     95          */
     96         int ERROR_NULL = 4;
     97         /**
     98          * Indicates that {@link com.android.server.InputMethodManagerService} recognizes no IME.
     99          */
    100         int ERROR_NO_IME = 5;
    101         /**
    102          * Indicates that {@link android.view.inputmethod.EditorInfo#packageName} does not match
    103          * the caller UID.
    104          *
    105          * @see android.view.inputmethod.EditorInfo#packageName
    106          */
    107         int ERROR_INVALID_PACKAGE_NAME = 6;
    108         /**
    109          * Indicates that the system is still in an early stage of the boot process and any 3rd
    110          * party application is not allowed to run.
    111          *
    112          * @see com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START
    113          */
    114         int ERROR_SYSTEM_NOT_READY = 7;
    115         /**
    116          * Indicates that {@link com.android.server.InputMethodManagerService} tried to connect to
    117          * an {@link android.inputmethodservice.InputMethodService} but failed.
    118          *
    119          * @see android.content.Context#bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)
    120          */
    121         int ERROR_IME_NOT_CONNECTED = 8;
    122         /**
    123          * Indicates that the caller is not the foreground user (or does not have
    124          * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission).
    125          */
    126         int ERROR_INVALID_USER = 9;
    127         /**
    128          * Indicates that the caller should have specified non-null
    129          * {@link android.view.inputmethod.EditorInfo}.
    130          */
    131         int ERROR_NULL_EDITOR_INFO = 10;
    132         /**
    133          * Indicates that the target window the client specified cannot be the IME target right now.
    134          *
    135          * <p>Due to the asynchronous nature of Android OS, we cannot completely avoid this error.
    136          * The client should try to restart input when its {@link android.view.Window} is focused
    137          * again.</p>
    138          *
    139          * @see com.android.server.wm.WindowManagerService#inputMethodClientHasFocus(IInputMethodClient)
    140          */
    141         int ERROR_NOT_IME_TARGET_WINDOW = 11;
    142         /**
    143          * Indicates that focused view in the current window is not an editor.
    144          */
    145         int ERROR_NO_EDITOR = 12;
    146     }
    147 
    148     @ResultCode
    149     public final int result;
    150 
    151     /**
    152      * The input method service.
    153      */
    154     public final IInputMethodSession method;
    155 
    156     /**
    157      * The input channel used to send input events to this IME.
    158      */
    159     public final InputChannel channel;
    160 
    161     /**
    162      * The ID for this input method, as found in InputMethodInfo; null if
    163      * no input method will be bound.
    164      */
    165     public final String id;
    166 
    167     /**
    168      * Sequence number of this binding.
    169      */
    170     public final int sequence;
    171 
    172     /**
    173      * Sequence number of user action notification.
    174      */
    175     public final int userActionNotificationSequenceNumber;
    176 
    177     public InputBindResult(@ResultCode int _result,
    178             IInputMethodSession _method, InputChannel _channel,
    179             String _id, int _sequence, int _userActionNotificationSequenceNumber) {
    180         result = _result;
    181         method = _method;
    182         channel = _channel;
    183         id = _id;
    184         sequence = _sequence;
    185         userActionNotificationSequenceNumber = _userActionNotificationSequenceNumber;
    186     }
    187 
    188     InputBindResult(Parcel source) {
    189         result = source.readInt();
    190         method = IInputMethodSession.Stub.asInterface(source.readStrongBinder());
    191         if (source.readInt() != 0) {
    192             channel = InputChannel.CREATOR.createFromParcel(source);
    193         } else {
    194             channel = null;
    195         }
    196         id = source.readString();
    197         sequence = source.readInt();
    198         userActionNotificationSequenceNumber = source.readInt();
    199     }
    200 
    201     @Override
    202     public String toString() {
    203         return "InputBindResult{result=" + getResultString() + " method="+ method + " id=" + id
    204                 + " sequence=" + sequence
    205                 + " userActionNotificationSequenceNumber=" + userActionNotificationSequenceNumber
    206                 + "}";
    207     }
    208 
    209     /**
    210      * Used to package this object into a {@link Parcel}.
    211      *
    212      * @param dest The {@link Parcel} to be written.
    213      * @param flags The flags used for parceling.
    214      */
    215     @Override
    216     public void writeToParcel(Parcel dest, int flags) {
    217         dest.writeInt(result);
    218         dest.writeStrongInterface(method);
    219         if (channel != null) {
    220             dest.writeInt(1);
    221             channel.writeToParcel(dest, flags);
    222         } else {
    223             dest.writeInt(0);
    224         }
    225         dest.writeString(id);
    226         dest.writeInt(sequence);
    227         dest.writeInt(userActionNotificationSequenceNumber);
    228     }
    229 
    230     /**
    231      * Used to make this class parcelable.
    232      */
    233     public static final Parcelable.Creator<InputBindResult> CREATOR =
    234             new Parcelable.Creator<InputBindResult>() {
    235         @Override
    236         public InputBindResult createFromParcel(Parcel source) {
    237             return new InputBindResult(source);
    238         }
    239 
    240         @Override
    241         public InputBindResult[] newArray(int size) {
    242             return new InputBindResult[size];
    243         }
    244     };
    245 
    246     @Override
    247     public int describeContents() {
    248         return channel != null ? channel.describeContents() : 0;
    249     }
    250 
    251     public String getResultString() {
    252         switch (result) {
    253             case ResultCode.SUCCESS_WITH_IME_SESSION:
    254                 return "SUCCESS_WITH_IME_SESSION";
    255             case ResultCode.SUCCESS_WAITING_IME_SESSION:
    256                 return "SUCCESS_WAITING_IME_SESSION";
    257             case ResultCode.SUCCESS_WAITING_IME_BINDING:
    258                 return "SUCCESS_WAITING_IME_BINDING";
    259             case ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY:
    260                 return "SUCCESS_REPORT_WINDOW_FOCUS_ONLY";
    261             case ResultCode.ERROR_NULL:
    262                 return "ERROR_NULL";
    263             case ResultCode.ERROR_NO_IME:
    264                 return "ERROR_NO_IME";
    265             case ResultCode.ERROR_NO_EDITOR:
    266                 return "ERROR_NO_EDITOR";
    267             case ResultCode.ERROR_INVALID_PACKAGE_NAME:
    268                 return "ERROR_INVALID_PACKAGE_NAME";
    269             case ResultCode.ERROR_SYSTEM_NOT_READY:
    270                 return "ERROR_SYSTEM_NOT_READY";
    271             case ResultCode.ERROR_IME_NOT_CONNECTED:
    272                 return "ERROR_IME_NOT_CONNECTED";
    273             case ResultCode.ERROR_INVALID_USER:
    274                 return "ERROR_INVALID_USER";
    275             case ResultCode.ERROR_NULL_EDITOR_INFO:
    276                 return "ERROR_NULL_EDITOR_INFO";
    277             case ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
    278                 return "ERROR_NOT_IME_TARGET_WINDOW";
    279             default:
    280                 return "Unknown(" + result + ")";
    281         }
    282     }
    283 
    284     private static InputBindResult error(@ResultCode int result) {
    285         return new InputBindResult(result, null, null, null, -1, -1);
    286     }
    287 
    288     /**
    289      * Predefined error object for {@link ResultCode#ERROR_NULL}.
    290      */
    291     public static final InputBindResult NULL = error(ResultCode.ERROR_NULL);
    292     /**
    293      * Predefined error object for {@link ResultCode#NO_IME}.
    294      */
    295     public static final InputBindResult NO_IME = error(ResultCode.ERROR_NO_IME);
    296     /**
    297      * Predefined error object for {@link ResultCode#NO_EDITOR}.
    298      */
    299     public static final InputBindResult NO_EDITOR = error(ResultCode.ERROR_NO_EDITOR);
    300     /**
    301      * Predefined error object for {@link ResultCode#ERROR_INVALID_PACKAGE_NAME}.
    302      */
    303     public static final InputBindResult INVALID_PACKAGE_NAME =
    304             error(ResultCode.ERROR_INVALID_PACKAGE_NAME);
    305     /**
    306      * Predefined error object for {@link ResultCode#ERROR_NULL_EDITOR_INFO}.
    307      */
    308     public static final InputBindResult NULL_EDITOR_INFO = error(ResultCode.ERROR_NULL_EDITOR_INFO);
    309     /**
    310      * Predefined error object for {@link ResultCode#ERROR_NOT_IME_TARGET_WINDOW}.
    311      */
    312     public static final InputBindResult NOT_IME_TARGET_WINDOW =
    313             error(ResultCode.ERROR_NOT_IME_TARGET_WINDOW);
    314     /**
    315      * Predefined error object for {@link ResultCode#ERROR_IME_NOT_CONNECTED}.
    316      */
    317     public static final InputBindResult IME_NOT_CONNECTED =
    318             error(ResultCode.ERROR_IME_NOT_CONNECTED);
    319     /**
    320      * Predefined error object for {@link ResultCode#ERROR_INVALID_USER}.
    321      */
    322     public static final InputBindResult INVALID_USER = error(ResultCode.ERROR_INVALID_USER);
    323 
    324 }
    325