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