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