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 17package com.android.internal.view; 18 19import static java.lang.annotation.RetentionPolicy.SOURCE; 20 21import android.annotation.IntDef; 22import android.content.ComponentName; 23import android.content.Intent; 24import android.content.ServiceConnection; 25import android.os.IBinder; 26import android.os.Parcel; 27import android.os.Parcelable; 28import android.os.UserHandle; 29import android.view.InputChannel; 30 31import 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 */ 37public 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