1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.mockime; 18 19 import static android.inputmethodservice.InputMethodService.FINISH_INPUT_NO_FALLBACK_CONNECTION; 20 21 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 22 23 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 24 25 import android.app.UiAutomation; 26 import android.app.compat.CompatChanges; 27 import android.content.BroadcastReceiver; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.IntentFilter; 32 import android.content.pm.PackageManager; 33 import android.os.Bundle; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.ParcelFileDescriptor; 37 import android.os.SystemClock; 38 import android.os.UserHandle; 39 import android.provider.Settings; 40 import android.text.TextUtils; 41 import android.view.KeyEvent; 42 import android.view.inputmethod.CompletionInfo; 43 import android.view.inputmethod.CorrectionInfo; 44 import android.view.inputmethod.ExtractedTextRequest; 45 import android.view.inputmethod.InputConnection; 46 import android.view.inputmethod.InputContentInfo; 47 import android.view.inputmethod.InputMethodManager; 48 49 import androidx.annotation.GuardedBy; 50 import androidx.annotation.NonNull; 51 import androidx.annotation.Nullable; 52 53 import com.android.compatibility.common.util.PollingCheck; 54 55 import org.junit.AssumptionViolatedException; 56 57 import java.io.IOException; 58 import java.util.concurrent.TimeUnit; 59 import java.util.concurrent.atomic.AtomicBoolean; 60 61 /** 62 * Represents an active Mock IME session, which provides basic primitives to write end-to-end tests 63 * for IME APIs. 64 * 65 * <p>To use {@link MockIme} via {@link MockImeSession}, you need to </p> 66 * <p>Public methods are not thread-safe.</p> 67 */ 68 public class MockImeSession implements AutoCloseable { 69 private final String mImeEventActionName = 70 "com.android.cts.mockime.action.IME_EVENT." + SystemClock.elapsedRealtimeNanos(); 71 72 private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(10); 73 74 @NonNull 75 private final Context mContext; 76 @NonNull 77 private final UiAutomation mUiAutomation; 78 79 private final HandlerThread mHandlerThread = new HandlerThread("EventReceiver"); 80 81 private static final class EventStore { 82 private static final int INITIAL_ARRAY_SIZE = 32; 83 84 @NonNull 85 public final ImeEvent[] mArray; 86 public int mLength; 87 EventStore()88 EventStore() { 89 mArray = new ImeEvent[INITIAL_ARRAY_SIZE]; 90 mLength = 0; 91 } 92 EventStore(EventStore src, int newLength)93 EventStore(EventStore src, int newLength) { 94 mArray = new ImeEvent[newLength]; 95 mLength = src.mLength; 96 System.arraycopy(src.mArray, 0, mArray, 0, src.mLength); 97 } 98 add(ImeEvent event)99 public EventStore add(ImeEvent event) { 100 if (mLength + 1 <= mArray.length) { 101 mArray[mLength] = event; 102 ++mLength; 103 return this; 104 } else { 105 return new EventStore(this, mLength * 2).add(event); 106 } 107 } 108 takeSnapshot()109 public ImeEventStream.ImeEventArray takeSnapshot() { 110 return new ImeEventStream.ImeEventArray(mArray, mLength); 111 } 112 } 113 114 private static final class MockImeEventReceiver extends BroadcastReceiver { 115 private final Object mLock = new Object(); 116 117 @GuardedBy("mLock") 118 @NonNull 119 private EventStore mCurrentEventStore = new EventStore(); 120 121 @NonNull 122 private final String mActionName; 123 MockImeEventReceiver(@onNull String actionName)124 MockImeEventReceiver(@NonNull String actionName) { 125 mActionName = actionName; 126 } 127 128 @Override onReceive(Context context, Intent intent)129 public void onReceive(Context context, Intent intent) { 130 if (TextUtils.equals(mActionName, intent.getAction())) { 131 synchronized (mLock) { 132 mCurrentEventStore = 133 mCurrentEventStore.add(ImeEvent.fromBundle(intent.getExtras())); 134 } 135 } 136 } 137 takeEventSnapshot()138 public ImeEventStream.ImeEventArray takeEventSnapshot() { 139 synchronized (mLock) { 140 return mCurrentEventStore.takeSnapshot(); 141 } 142 } 143 } 144 private final MockImeEventReceiver mEventReceiver = 145 new MockImeEventReceiver(mImeEventActionName); 146 147 private final ImeEventStream mEventStream = 148 new ImeEventStream(mEventReceiver::takeEventSnapshot); 149 executeShellCommand( @onNull UiAutomation uiAutomation, @NonNull String command)150 private static String executeShellCommand( 151 @NonNull UiAutomation uiAutomation, @NonNull String command) throws IOException { 152 try (ParcelFileDescriptor.AutoCloseInputStream in = 153 new ParcelFileDescriptor.AutoCloseInputStream( 154 uiAutomation.executeShellCommand(command))) { 155 final StringBuilder sb = new StringBuilder(); 156 final byte[] buffer = new byte[4096]; 157 while (true) { 158 final int numRead = in.read(buffer); 159 if (numRead <= 0) { 160 break; 161 } 162 sb.append(new String(buffer, 0, numRead)); 163 } 164 return sb.toString(); 165 } 166 } 167 168 @Nullable getCurrentInputMethodId()169 private String getCurrentInputMethodId() { 170 // TODO: Replace this with IMM#getCurrentInputMethodIdForTesting() 171 return Settings.Secure.getString(mContext.getContentResolver(), 172 Settings.Secure.DEFAULT_INPUT_METHOD); 173 } 174 175 @Nullable writeMockImeSettings(@onNull Context context, @NonNull String imeEventActionName, @Nullable ImeSettings.Builder imeSettings)176 private static void writeMockImeSettings(@NonNull Context context, 177 @NonNull String imeEventActionName, 178 @Nullable ImeSettings.Builder imeSettings) throws Exception { 179 final Bundle bundle = ImeSettings.serializeToBundle(imeEventActionName, imeSettings); 180 context.getContentResolver().call(SettingsProvider.AUTHORITY, "write", null, bundle); 181 } 182 getMockImeComponentName()183 private ComponentName getMockImeComponentName() { 184 return MockIme.getComponentName(); 185 } 186 getMockImeId()187 private String getMockImeId() { 188 return MockIme.getImeId(); 189 } 190 MockImeSession(@onNull Context context, @NonNull UiAutomation uiAutomation)191 private MockImeSession(@NonNull Context context, @NonNull UiAutomation uiAutomation) { 192 mContext = context; 193 mUiAutomation = uiAutomation; 194 } 195 initialize(@ullable ImeSettings.Builder imeSettings)196 private void initialize(@Nullable ImeSettings.Builder imeSettings) throws Exception { 197 // Make sure that MockIME is not selected. 198 if (mContext.getSystemService(InputMethodManager.class) 199 .getInputMethodList() 200 .stream() 201 .anyMatch(info -> getMockImeComponentName().equals(info.getComponent()))) { 202 executeShellCommand(mUiAutomation, "ime reset"); 203 } 204 if (mContext.getSystemService(InputMethodManager.class) 205 .getEnabledInputMethodList() 206 .stream() 207 .anyMatch(info -> getMockImeComponentName().equals(info.getComponent()))) { 208 throw new IllegalStateException(); 209 } 210 211 writeMockImeSettings(mContext, mImeEventActionName, imeSettings); 212 213 mHandlerThread.start(); 214 mContext.registerReceiver(mEventReceiver, 215 new IntentFilter(mImeEventActionName), null /* broadcastPermission */, 216 new Handler(mHandlerThread.getLooper())); 217 218 executeShellCommand(mUiAutomation, "ime enable " + getMockImeId()); 219 executeShellCommand(mUiAutomation, "ime set " + getMockImeId()); 220 221 PollingCheck.check("Make sure that MockIME becomes available", TIMEOUT, 222 () -> getMockImeId().equals(getCurrentInputMethodId())); 223 } 224 225 /** @see #create(Context, UiAutomation, ImeSettings.Builder) */ 226 @NonNull create(@onNull Context context)227 public static MockImeSession create(@NonNull Context context) throws Exception { 228 return create(context, getInstrumentation().getUiAutomation(), new ImeSettings.Builder()); 229 } 230 231 /** 232 * Creates a new Mock IME session. During this session, you can receive various events from 233 * {@link MockIme}. 234 * 235 * @param context {@link Context} to be used to receive inter-process events from the 236 * {@link MockIme} (e.g. via {@link BroadcastReceiver} 237 * @param uiAutomation {@link UiAutomation} object to change the device state that are typically 238 * guarded by permissions. 239 * @param imeSettings Key-value pairs to be passed to the {@link MockIme}. 240 * @return A session object, with which you can retrieve event logs from the {@link MockIme} and 241 * can clean up the session. 242 */ 243 @NonNull create( @onNull Context context, @NonNull UiAutomation uiAutomation, @Nullable ImeSettings.Builder imeSettings)244 public static MockImeSession create( 245 @NonNull Context context, 246 @NonNull UiAutomation uiAutomation, 247 @Nullable ImeSettings.Builder imeSettings) throws Exception { 248 final String unavailabilityReason = getUnavailabilityReason(context); 249 if (unavailabilityReason != null) { 250 throw new AssumptionViolatedException(unavailabilityReason); 251 } 252 253 final MockImeSession client = new MockImeSession(context, uiAutomation); 254 client.initialize(imeSettings); 255 return client; 256 } 257 258 /** 259 * Checks if the {@link MockIme} can be used in this device. 260 * 261 * @return {@code null} if it can be used, or message describing why if it cannot. 262 */ 263 @Nullable getUnavailabilityReason(@onNull Context context)264 public static String getUnavailabilityReason(@NonNull Context context) { 265 if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)) { 266 return "Device must support installable IMEs that implement InputMethodService API"; 267 } 268 return null; 269 } 270 271 /** 272 * Whether {@link MockIme} enabled a compatibility flag to finish input without fallback 273 * input connection when device interactive state changed. See detailed description in 274 * {@link MockImeSession#setEnabledFinishInputNoFallbackConnection}. 275 * 276 * @return {@code true} if the compatibility flag is enabled. 277 */ isFinishInputNoFallbackConnectionEnabled()278 public static boolean isFinishInputNoFallbackConnectionEnabled() { 279 AtomicBoolean result = new AtomicBoolean(); 280 runWithShellPermissionIdentity(() -> 281 result.set(CompatChanges.isChangeEnabled(FINISH_INPUT_NO_FALLBACK_CONNECTION, 282 MockIme.getComponentName().getPackageName(), UserHandle.CURRENT))); 283 return result.get(); 284 } 285 286 /** 287 * @return {@link ImeEventStream} object that stores events sent from {@link MockIme} since the 288 * session is created. 289 */ openEventStream()290 public ImeEventStream openEventStream() { 291 return mEventStream.copy(); 292 } 293 294 /** 295 * Closes the active session and de-selects {@link MockIme}. Currently which IME will be 296 * selected next is up to the system. 297 */ close()298 public void close() throws Exception { 299 executeShellCommand(mUiAutomation, "ime reset"); 300 301 PollingCheck.check("Make sure that MockIME becomes unavailable", TIMEOUT, () -> 302 mContext.getSystemService(InputMethodManager.class) 303 .getEnabledInputMethodList() 304 .stream() 305 .noneMatch(info -> getMockImeComponentName().equals(info.getComponent()))); 306 mContext.unregisterReceiver(mEventReceiver); 307 mHandlerThread.quitSafely(); 308 mContext.getContentResolver().call(SettingsProvider.AUTHORITY, "delete", null, null); 309 } 310 311 /** 312 * Common logic to send a special command to {@link MockIme}. 313 * 314 * @param commandName command to be passed to {@link MockIme} 315 * @param params {@link Bundle} to be passed to {@link MockIme} as a parameter set of 316 * {@code commandName} 317 * @return {@link ImeCommand} that is sent to {@link MockIme}. It can be passed to 318 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 319 * wait until this event is handled by {@link MockIme}. 320 */ 321 @NonNull callCommandInternal(@onNull String commandName, @NonNull Bundle params)322 private ImeCommand callCommandInternal(@NonNull String commandName, @NonNull Bundle params) { 323 final ImeCommand command = new ImeCommand( 324 commandName, SystemClock.elapsedRealtimeNanos(), true, params); 325 final Intent intent = new Intent(); 326 intent.setPackage(MockIme.getComponentName().getPackageName()); 327 intent.setAction(MockIme.getCommandActionName(mImeEventActionName)); 328 intent.putExtras(command.toBundle()); 329 mContext.sendBroadcast(intent); 330 return command; 331 } 332 333 /** 334 * Lets {@link MockIme} to call 335 * {@link android.inputmethodservice.InputMethodService#getCurrentInputConnection()} and 336 * memorize it for later {@link InputConnection}-related operations. 337 * 338 * <p>Only the last one will be memorized if this method gets called multiple times.</p> 339 * 340 * @return {@link ImeCommand} object that can be passed to 341 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 342 * wait until this event is handled by {@link MockIme}. 343 * @see #unmemorizeCurrentInputConnection() 344 */ 345 @NonNull memorizeCurrentInputConnection()346 public ImeCommand memorizeCurrentInputConnection() { 347 final Bundle params = new Bundle(); 348 return callCommandInternal("memorizeCurrentInputConnection", params); 349 } 350 351 /** 352 * Lets {@link MockIme} to forget memorized {@link InputConnection} if any. Does nothing 353 * otherwise. 354 * 355 * @return {@link ImeCommand} object that can be passed to 356 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 357 * wait until this event is handled by {@link MockIme}. 358 * @see #memorizeCurrentInputConnection() 359 */ 360 @NonNull unmemorizeCurrentInputConnection()361 public ImeCommand unmemorizeCurrentInputConnection() { 362 final Bundle params = new Bundle(); 363 return callCommandInternal("unmemorizeCurrentInputConnection", params); 364 } 365 366 /** 367 * Lets {@link MockIme} to call {@link InputConnection#getTextBeforeCursor(int, int)} with the 368 * given parameters. 369 * 370 * <p>This triggers {@code getCurrentInputConnection().getTextBeforeCursor(n, flag)}.</p> 371 * 372 * <p>Use {@link ImeEvent#getReturnCharSequenceValue()} for {@link ImeEvent} returned from 373 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 374 * value returned from the API.</p> 375 * 376 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 377 * 378 * @param n to be passed as the {@code n} parameter. 379 * @param flag to be passed as the {@code flag} parameter. 380 * @return {@link ImeCommand} object that can be passed to 381 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 382 * wait until this event is handled by {@link MockIme}. 383 */ 384 @NonNull callGetTextBeforeCursor(int n, int flag)385 public ImeCommand callGetTextBeforeCursor(int n, int flag) { 386 final Bundle params = new Bundle(); 387 params.putInt("n", n); 388 params.putInt("flag", flag); 389 return callCommandInternal("getTextBeforeCursor", params); 390 } 391 392 /** 393 * Lets {@link MockIme} to call {@link InputConnection#getTextAfterCursor(int, int)} with the 394 * given parameters. 395 * 396 * <p>This triggers {@code getCurrentInputConnection().getTextAfterCursor(n, flag)}.</p> 397 * 398 * <p>Use {@link ImeEvent#getReturnCharSequenceValue()} for {@link ImeEvent} returned from 399 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 400 * value returned from the API.</p> 401 * 402 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 403 * 404 * @param n to be passed as the {@code n} parameter. 405 * @param flag to be passed as the {@code flag} parameter. 406 * @return {@link ImeCommand} object that can be passed to 407 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 408 * wait until this event is handled by {@link MockIme}. 409 */ 410 @NonNull callGetTextAfterCursor(int n, int flag)411 public ImeCommand callGetTextAfterCursor(int n, int flag) { 412 final Bundle params = new Bundle(); 413 params.putInt("n", n); 414 params.putInt("flag", flag); 415 return callCommandInternal("getTextAfterCursor", params); 416 } 417 418 /** 419 * Lets {@link MockIme} to call {@link InputConnection#getSelectedText(int)} with the 420 * given parameters. 421 * 422 * <p>This triggers {@code getCurrentInputConnection().getSelectedText(flag)}.</p> 423 * 424 * <p>Use {@link ImeEvent#getReturnCharSequenceValue()} for {@link ImeEvent} returned from 425 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 426 * value returned from the API.</p> 427 * 428 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 429 * 430 * @param flag to be passed as the {@code flag} parameter. 431 * @return {@link ImeCommand} object that can be passed to 432 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 433 * wait until this event is handled by {@link MockIme}. 434 */ 435 @NonNull callGetSelectedText(int flag)436 public ImeCommand callGetSelectedText(int flag) { 437 final Bundle params = new Bundle(); 438 params.putInt("flag", flag); 439 return callCommandInternal("getSelectedText", params); 440 } 441 442 /** 443 * Lets {@link MockIme} to call {@link InputConnection#getCursorCapsMode(int)} with the given 444 * parameters. 445 * 446 * <p>This triggers {@code getCurrentInputConnection().getCursorCapsMode(reqModes)}.</p> 447 * 448 * <p>Use {@link ImeEvent#getReturnIntegerValue()} for {@link ImeEvent} returned from 449 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 450 * value returned from the API.</p> 451 * 452 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 453 * 454 * @param reqModes to be passed as the {@code reqModes} parameter. 455 * @return {@link ImeCommand} object that can be passed to 456 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 457 * wait until this event is handled by {@link MockIme}. 458 */ 459 @NonNull callGetCursorCapsMode(int reqModes)460 public ImeCommand callGetCursorCapsMode(int reqModes) { 461 final Bundle params = new Bundle(); 462 params.putInt("reqModes", reqModes); 463 return callCommandInternal("getCursorCapsMode", params); 464 } 465 466 /** 467 * Lets {@link MockIme} to call 468 * {@link InputConnection#getExtractedText(ExtractedTextRequest, int)} with the given 469 * parameters. 470 * 471 * <p>This triggers {@code getCurrentInputConnection().getExtractedText(request, flags)}.</p> 472 * 473 * <p>Use {@link ImeEvent#getReturnParcelableValue()} for {@link ImeEvent} returned from 474 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 475 * value returned from the API.</p> 476 * 477 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 478 * 479 * @param request to be passed as the {@code request} parameter 480 * @param flags to be passed as the {@code flags} parameter 481 * @return {@link ImeCommand} object that can be passed to 482 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 483 * wait until this event is handled by {@link MockIme}. 484 */ 485 @NonNull callGetExtractedText(@ullable ExtractedTextRequest request, int flags)486 public ImeCommand callGetExtractedText(@Nullable ExtractedTextRequest request, int flags) { 487 final Bundle params = new Bundle(); 488 params.putParcelable("request", request); 489 params.putInt("flags", flags); 490 return callCommandInternal("getExtractedText", params); 491 } 492 493 /** 494 * Lets {@link MockIme} to call {@link InputConnection#deleteSurroundingText(int, int)} with the 495 * given parameters. 496 * 497 * <p>This triggers 498 * {@code getCurrentInputConnection().deleteSurroundingText(beforeLength, afterLength)}.</p> 499 * 500 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 501 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 502 * value returned from the API.</p> 503 * 504 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 505 * 506 * @param beforeLength to be passed as the {@code beforeLength} parameter 507 * @param afterLength to be passed as the {@code afterLength} parameter 508 * @return {@link ImeCommand} object that can be passed to 509 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 510 * wait until this event is handled by {@link MockIme}. 511 */ 512 @NonNull callDeleteSurroundingText(int beforeLength, int afterLength)513 public ImeCommand callDeleteSurroundingText(int beforeLength, int afterLength) { 514 final Bundle params = new Bundle(); 515 params.putInt("beforeLength", beforeLength); 516 params.putInt("afterLength", afterLength); 517 return callCommandInternal("deleteSurroundingText", params); 518 } 519 520 /** 521 * Lets {@link MockIme} to call 522 * {@link InputConnection#deleteSurroundingTextInCodePoints(int, int)} with the given 523 * parameters. 524 * 525 * <p>This triggers {@code getCurrentInputConnection().deleteSurroundingTextInCodePoints( 526 * beforeLength, afterLength)}.</p> 527 * 528 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 529 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 530 * value returned from the API.</p> 531 * 532 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 533 * 534 * @param beforeLength to be passed as the {@code beforeLength} parameter 535 * @param afterLength to be passed as the {@code afterLength} parameter 536 * @return {@link ImeCommand} object that can be passed to 537 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 538 * wait until this event is handled by {@link MockIme}. 539 */ 540 @NonNull callDeleteSurroundingTextInCodePoints(int beforeLength, int afterLength)541 public ImeCommand callDeleteSurroundingTextInCodePoints(int beforeLength, int afterLength) { 542 final Bundle params = new Bundle(); 543 params.putInt("beforeLength", beforeLength); 544 params.putInt("afterLength", afterLength); 545 return callCommandInternal("deleteSurroundingTextInCodePoints", params); 546 } 547 548 /** 549 * Lets {@link MockIme} to call {@link InputConnection#setComposingText(CharSequence, int)} with 550 * the given parameters. 551 * 552 * <p>This triggers 553 * {@code getCurrentInputConnection().setComposingText(text, newCursorPosition)}.</p> 554 * 555 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 556 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 557 * value returned from the API.</p> 558 * 559 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 560 * 561 * @param text to be passed as the {@code text} parameter 562 * @param newCursorPosition to be passed as the {@code newCursorPosition} parameter 563 * @return {@link ImeCommand} object that can be passed to 564 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 565 * wait until this event is handled by {@link MockIme}. 566 */ 567 @NonNull callSetComposingText(@ullable CharSequence text, int newCursorPosition)568 public ImeCommand callSetComposingText(@Nullable CharSequence text, int newCursorPosition) { 569 final Bundle params = new Bundle(); 570 params.putCharSequence("text", text); 571 params.putInt("newCursorPosition", newCursorPosition); 572 return callCommandInternal("setComposingText", params); 573 } 574 575 /** 576 * Lets {@link MockIme} to call {@link InputConnection#setComposingRegion(int, int)} with the 577 * given parameters. 578 * 579 * <p>This triggers {@code getCurrentInputConnection().setComposingRegion(start, end)}.</p> 580 * 581 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 582 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 583 * value returned from the API.</p> 584 * 585 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 586 * 587 * @param start to be passed as the {@code start} parameter 588 * @param end to be passed as the {@code end} parameter 589 * @return {@link ImeCommand} object that can be passed to 590 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 591 * wait until this event is handled by {@link MockIme}. 592 */ 593 @NonNull callSetComposingRegion(int start, int end)594 public ImeCommand callSetComposingRegion(int start, int end) { 595 final Bundle params = new Bundle(); 596 params.putInt("start", start); 597 params.putInt("end", end); 598 return callCommandInternal("setComposingRegion", params); 599 } 600 601 /** 602 * Lets {@link MockIme} to call {@link InputConnection#finishComposingText()} with the given 603 * parameters. 604 * 605 * <p>This triggers {@code getCurrentInputConnection().finishComposingText()}.</p> 606 * 607 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 608 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 609 * value returned from the API.</p> 610 * 611 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 612 * 613 * @return {@link ImeCommand} object that can be passed to 614 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 615 * wait until this event is handled by {@link MockIme}. 616 */ 617 @NonNull callFinishComposingText()618 public ImeCommand callFinishComposingText() { 619 final Bundle params = new Bundle(); 620 return callCommandInternal("finishComposingText", params); 621 } 622 623 /** 624 * Lets {@link MockIme} to call {@link InputConnection#commitText(CharSequence, int)} with the 625 * given parameters. 626 * 627 * <p>This triggers {@code getCurrentInputConnection().commitText(text, newCursorPosition)}.</p> 628 * 629 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 630 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 631 * value returned from the API.</p> 632 * 633 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 634 * 635 * @param text to be passed as the {@code text} parameter 636 * @param newCursorPosition to be passed as the {@code newCursorPosition} parameter 637 * @return {@link ImeCommand} object that can be passed to 638 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 639 * wait until this event is handled by {@link MockIme} 640 */ 641 @NonNull callCommitText(@ullable CharSequence text, int newCursorPosition)642 public ImeCommand callCommitText(@Nullable CharSequence text, int newCursorPosition) { 643 final Bundle params = new Bundle(); 644 params.putCharSequence("text", text); 645 params.putInt("newCursorPosition", newCursorPosition); 646 return callCommandInternal("commitText", params); 647 } 648 649 /** 650 * Lets {@link MockIme} to call {@link InputConnection#commitCompletion(CompletionInfo)} with 651 * the given parameters. 652 * 653 * <p>This triggers {@code getCurrentInputConnection().commitCompletion(text)}.</p> 654 * 655 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 656 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 657 * value returned from the API.</p> 658 * 659 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 660 * 661 * @param text to be passed as the {@code text} parameter 662 * @return {@link ImeCommand} object that can be passed to 663 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 664 * wait until this event is handled by {@link MockIme} 665 */ 666 @NonNull callCommitCompletion(@ullable CompletionInfo text)667 public ImeCommand callCommitCompletion(@Nullable CompletionInfo text) { 668 final Bundle params = new Bundle(); 669 params.putParcelable("text", text); 670 return callCommandInternal("commitCompletion", params); 671 } 672 673 /** 674 * Lets {@link MockIme} to call {@link InputConnection#commitCorrection(CorrectionInfo)} with 675 * the given parameters. 676 * 677 * <p>This triggers {@code getCurrentInputConnection().commitCorrection(correctionInfo)}.</p> 678 * 679 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 680 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 681 * value returned from the API.</p> 682 * 683 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 684 * 685 * @param correctionInfo to be passed as the {@code correctionInfo} parameter 686 * @return {@link ImeCommand} object that can be passed to 687 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 688 * wait until this event is handled by {@link MockIme} 689 */ 690 @NonNull callCommitCorrection(@ullable CorrectionInfo correctionInfo)691 public ImeCommand callCommitCorrection(@Nullable CorrectionInfo correctionInfo) { 692 final Bundle params = new Bundle(); 693 params.putParcelable("correctionInfo", correctionInfo); 694 return callCommandInternal("commitCorrection", params); 695 } 696 697 /** 698 * Lets {@link MockIme} to call {@link InputConnection#setSelection(int, int)} with the given 699 * parameters. 700 * 701 * <p>This triggers {@code getCurrentInputConnection().setSelection(start, end)}.</p> 702 * 703 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 704 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 705 * value returned from the API.</p> 706 * 707 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 708 * 709 * @param start to be passed as the {@code start} parameter 710 * @param end to be passed as the {@code end} parameter 711 * @return {@link ImeCommand} object that can be passed to 712 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 713 * wait until this event is handled by {@link MockIme} 714 */ 715 @NonNull callSetSelection(int start, int end)716 public ImeCommand callSetSelection(int start, int end) { 717 final Bundle params = new Bundle(); 718 params.putInt("start", start); 719 params.putInt("end", end); 720 return callCommandInternal("setSelection", params); 721 } 722 723 /** 724 * Lets {@link MockIme} to call {@link InputConnection#performEditorAction(int)} with the given 725 * parameters. 726 * 727 * <p>This triggers {@code getCurrentInputConnection().performEditorAction(editorAction)}.</p> 728 * 729 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 730 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 731 * value returned from the API.</p> 732 * 733 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 734 * 735 * @param editorAction to be passed as the {@code editorAction} parameter 736 * @return {@link ImeCommand} object that can be passed to 737 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 738 * wait until this event is handled by {@link MockIme} 739 */ 740 @NonNull callPerformEditorAction(int editorAction)741 public ImeCommand callPerformEditorAction(int editorAction) { 742 final Bundle params = new Bundle(); 743 params.putInt("editorAction", editorAction); 744 return callCommandInternal("performEditorAction", params); 745 } 746 747 /** 748 * Lets {@link MockIme} to call {@link InputConnection#performContextMenuAction(int)} with the 749 * given parameters. 750 * 751 * <p>This triggers {@code getCurrentInputConnection().performContextMenuAction(id)}.</p> 752 * 753 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 754 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 755 * value returned from the API.</p> 756 * 757 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 758 * 759 * @param id to be passed as the {@code id} parameter 760 * @return {@link ImeCommand} object that can be passed to 761 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 762 * wait until this event is handled by {@link MockIme} 763 */ 764 @NonNull callPerformContextMenuAction(int id)765 public ImeCommand callPerformContextMenuAction(int id) { 766 final Bundle params = new Bundle(); 767 params.putInt("id", id); 768 return callCommandInternal("performContextMenuAction", params); 769 } 770 771 /** 772 * Lets {@link MockIme} to call {@link InputConnection#beginBatchEdit()} with the given 773 * parameters. 774 * 775 * <p>This triggers {@code getCurrentInputConnection().beginBatchEdit()}.</p> 776 * 777 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 778 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 779 * value returned from the API.</p> 780 * 781 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 782 * 783 * @return {@link ImeCommand} object that can be passed to 784 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 785 * wait until this event is handled by {@link MockIme} 786 */ 787 @NonNull callBeginBatchEdit()788 public ImeCommand callBeginBatchEdit() { 789 final Bundle params = new Bundle(); 790 return callCommandInternal("beginBatchEdit", params); 791 } 792 793 /** 794 * Lets {@link MockIme} to call {@link InputConnection#endBatchEdit()} with the given 795 * parameters. 796 * 797 * <p>This triggers {@code getCurrentInputConnection().endBatchEdit()}.</p> 798 * 799 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 800 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 801 * value returned from the API.</p> 802 * 803 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 804 * 805 * @return {@link ImeCommand} object that can be passed to 806 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 807 * wait until this event is handled by {@link MockIme} 808 */ 809 @NonNull callEndBatchEdit()810 public ImeCommand callEndBatchEdit() { 811 final Bundle params = new Bundle(); 812 return callCommandInternal("endBatchEdit", params); 813 } 814 815 /** 816 * Lets {@link MockIme} to call {@link InputConnection#sendKeyEvent(KeyEvent)} with the given 817 * parameters. 818 * 819 * <p>This triggers {@code getCurrentInputConnection().sendKeyEvent(event)}.</p> 820 * 821 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 822 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 823 * value returned from the API.</p> 824 * 825 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 826 * 827 * @param event to be passed as the {@code event} parameter 828 * @return {@link ImeCommand} object that can be passed to 829 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 830 * wait until this event is handled by {@link MockIme} 831 */ 832 @NonNull callSendKeyEvent(@ullable KeyEvent event)833 public ImeCommand callSendKeyEvent(@Nullable KeyEvent event) { 834 final Bundle params = new Bundle(); 835 params.putParcelable("event", event); 836 return callCommandInternal("sendKeyEvent", params); 837 } 838 839 /** 840 * Lets {@link MockIme} to call {@link InputConnection#performSpellCheck()}. 841 * 842 * <p>This triggers {@code getCurrentInputConnection().performSpellCheck()}.</p> 843 * 844 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 845 846 * @return {@link ImeCommand} object that can be passed to 847 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 848 * wait until this event is handled by {@link MockIme} 849 */ 850 @NonNull callPerformSpellCheck()851 public ImeCommand callPerformSpellCheck() { 852 return callCommandInternal("performSpellCheck", new Bundle()); 853 } 854 855 /** 856 * Lets {@link MockIme} to call {@link InputConnection#clearMetaKeyStates(int)} with the given 857 * parameters. 858 * 859 * <p>This triggers {@code getCurrentInputConnection().sendKeyEvent(event)}.</p> 860 * 861 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 862 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 863 * value returned from the API.</p> 864 * 865 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 866 * 867 * @param states to be passed as the {@code states} parameter 868 * @return {@link ImeCommand} object that can be passed to 869 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 870 * wait until this event is handled by {@link MockIme} 871 */ 872 @NonNull callClearMetaKeyStates(int states)873 public ImeCommand callClearMetaKeyStates(int states) { 874 final Bundle params = new Bundle(); 875 params.putInt("states", states); 876 return callCommandInternal("clearMetaKeyStates", params); 877 } 878 879 /** 880 * Lets {@link MockIme} to call {@link InputConnection#reportFullscreenMode(boolean)} with the 881 * given parameters. 882 * 883 * <p>This triggers {@code getCurrentInputConnection().reportFullscreenMode(enabled)}.</p> 884 * 885 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 886 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 887 * value returned from the API.</p> 888 * 889 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 890 * 891 * @param enabled to be passed as the {@code enabled} parameter 892 * @return {@link ImeCommand} object that can be passed to 893 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 894 * wait until this event is handled by {@link MockIme} 895 */ 896 @NonNull callReportFullscreenMode(boolean enabled)897 public ImeCommand callReportFullscreenMode(boolean enabled) { 898 final Bundle params = new Bundle(); 899 params.putBoolean("enabled", enabled); 900 return callCommandInternal("reportFullscreenMode", params); 901 } 902 903 /** 904 * Lets {@link MockIme} to call {@link InputConnection#performPrivateCommand(String, Bundle)} 905 * with the given parameters. 906 * 907 * <p>This triggers {@code getCurrentInputConnection().performPrivateCommand(action, data)}.</p> 908 * 909 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 910 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 911 * value returned from the API.</p> 912 * 913 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 914 * 915 * @param action to be passed as the {@code action} parameter 916 * @param data to be passed as the {@code data} parameter 917 * @return {@link ImeCommand} object that can be passed to 918 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 919 * wait until this event is handled by {@link MockIme} 920 */ 921 @NonNull callPerformPrivateCommand(@ullable String action, Bundle data)922 public ImeCommand callPerformPrivateCommand(@Nullable String action, Bundle data) { 923 final Bundle params = new Bundle(); 924 params.putString("action", action); 925 params.putBundle("data", data); 926 return callCommandInternal("performPrivateCommand", params); 927 } 928 929 /** 930 * Lets {@link MockIme} to call {@link InputConnection#requestCursorUpdates(int)} with the given 931 * parameters. 932 * 933 * <p>This triggers {@code getCurrentInputConnection().requestCursorUpdates(cursorUpdateMode)}. 934 * </p> 935 * 936 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 937 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 938 * value returned from the API.</p> 939 * 940 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 941 * 942 * @param cursorUpdateMode to be passed as the {@code cursorUpdateMode} parameter 943 * @return {@link ImeCommand} object that can be passed to 944 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 945 * wait until this event is handled by {@link MockIme} 946 */ 947 @NonNull callRequestCursorUpdates(int cursorUpdateMode)948 public ImeCommand callRequestCursorUpdates(int cursorUpdateMode) { 949 final Bundle params = new Bundle(); 950 params.putInt("cursorUpdateMode", cursorUpdateMode); 951 return callCommandInternal("requestCursorUpdates", params); 952 } 953 954 /** 955 * Lets {@link MockIme} to call {@link InputConnection#getHandler()} with the given parameters. 956 * 957 * <p>This triggers {@code getCurrentInputConnection().getHandler()}.</p> 958 * 959 * <p>Use {@link ImeEvent#isNullReturnValue()} for {@link ImeEvent} returned from 960 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 961 * value returned from the API was {@code null} or not.</p> 962 * 963 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 964 * 965 * @return {@link ImeCommand} object that can be passed to 966 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 967 * wait until this event is handled by {@link MockIme} 968 */ 969 @NonNull callGetHandler()970 public ImeCommand callGetHandler() { 971 final Bundle params = new Bundle(); 972 return callCommandInternal("getHandler", params); 973 } 974 975 /** 976 * Lets {@link MockIme} to call {@link InputConnection#closeConnection()} with the given 977 * parameters. 978 * 979 * <p>This triggers {@code getCurrentInputConnection().closeConnection()}.</p> 980 * 981 * <p>Return value information is not available for this command.</p> 982 * 983 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 984 * 985 * @return {@link ImeCommand} object that can be passed to 986 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 987 * wait until this event is handled by {@link MockIme} 988 */ 989 @NonNull callCloseConnection()990 public ImeCommand callCloseConnection() { 991 final Bundle params = new Bundle(); 992 return callCommandInternal("closeConnection", params); 993 } 994 995 /** 996 * Lets {@link MockIme} to call 997 * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} with the given 998 * parameters. 999 * 1000 * <p>This triggers 1001 * {@code getCurrentInputConnection().commitContent(inputContentInfo, flags, opts)}.</p> 1002 * 1003 * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from 1004 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the 1005 * value returned from the API.</p> 1006 * 1007 * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p> 1008 * 1009 * @param inputContentInfo to be passed as the {@code inputContentInfo} parameter 1010 * @param flags to be passed as the {@code flags} parameter 1011 * @param opts to be passed as the {@code opts} parameter 1012 * @return {@link ImeCommand} object that can be passed to 1013 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1014 * wait until this event is handled by {@link MockIme} 1015 */ 1016 @NonNull callCommitContent(@onNull InputContentInfo inputContentInfo, int flags, @Nullable Bundle opts)1017 public ImeCommand callCommitContent(@NonNull InputContentInfo inputContentInfo, int flags, 1018 @Nullable Bundle opts) { 1019 final Bundle params = new Bundle(); 1020 params.putParcelable("inputContentInfo", inputContentInfo); 1021 params.putInt("flags", flags); 1022 params.putBundle("opts", opts); 1023 return callCommandInternal("commitContent", params); 1024 } 1025 1026 /** 1027 * Lets {@link MockIme} to call 1028 * {@link android.inputmethodservice.InputMethodService#setBackDisposition(int)} with the given 1029 * parameters. 1030 * 1031 * <p>This triggers {@code setBackDisposition(backDisposition)}.</p> 1032 * 1033 * @param backDisposition to be passed as the {@code backDisposition} parameter 1034 * @return {@link ImeCommand} object that can be passed to 1035 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1036 * wait until this event is handled by {@link MockIme} 1037 */ 1038 @NonNull callSetBackDisposition(int backDisposition)1039 public ImeCommand callSetBackDisposition(int backDisposition) { 1040 final Bundle params = new Bundle(); 1041 params.putInt("backDisposition", backDisposition); 1042 return callCommandInternal("setBackDisposition", params); 1043 } 1044 1045 /** 1046 * Lets {@link MockIme} to call 1047 * {@link android.inputmethodservice.InputMethodService#requestHideSelf(int)} with the given 1048 * parameters. 1049 * 1050 * <p>This triggers {@code requestHideSelf(flags)}.</p> 1051 * 1052 * @param flags to be passed as the {@code flags} parameter 1053 * @return {@link ImeCommand} object that can be passed to 1054 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1055 * wait until this event is handled by {@link MockIme} 1056 */ 1057 @NonNull callRequestHideSelf(int flags)1058 public ImeCommand callRequestHideSelf(int flags) { 1059 final Bundle params = new Bundle(); 1060 params.putInt("flags", flags); 1061 return callCommandInternal("requestHideSelf", params); 1062 } 1063 1064 /** 1065 * Lets {@link MockIme} to call 1066 * {@link android.inputmethodservice.InputMethodService#requestShowSelf(int)} with the given 1067 * parameters. 1068 * 1069 * <p>This triggers {@code requestShowSelf(flags)}.</p> 1070 * 1071 * @param flags to be passed as the {@code flags} parameter 1072 * @return {@link ImeCommand} object that can be passed to 1073 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1074 * wait until this event is handled by {@link MockIme} 1075 */ 1076 @NonNull callRequestShowSelf(int flags)1077 public ImeCommand callRequestShowSelf(int flags) { 1078 final Bundle params = new Bundle(); 1079 params.putInt("flags", flags); 1080 return callCommandInternal("requestShowSelf", params); 1081 } 1082 1083 /** 1084 * Lets {@link MockIme} call 1085 * {@link android.inputmethodservice.InputMethodService#sendDownUpKeyEvents(int)} with the given 1086 * {@code keyEventCode}. 1087 * 1088 * @param keyEventCode to be passed as the {@code keyEventCode} parameter. 1089 * @return {@link ImeCommand} object that can be passed to 1090 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1091 * wait until this event is handled by {@link MockIme} 1092 */ 1093 @NonNull callSendDownUpKeyEvents(int keyEventCode)1094 public ImeCommand callSendDownUpKeyEvents(int keyEventCode) { 1095 final Bundle params = new Bundle(); 1096 params.putInt("keyEventCode", keyEventCode); 1097 return callCommandInternal("sendDownUpKeyEvents", params); 1098 } 1099 1100 /** 1101 * Lets {@link MockIme} call 1102 * {@link android.content.pm.PackageManager#getApplicationInfo(String, int)} with the given 1103 * {@code packageName} and {@code flags}. 1104 * 1105 * @param packageName the package name to be passed to 1106 * {@link android.content.pm.PackageManager#getApplicationInfo(String, int)}. 1107 * @param flags the flags to be passed to 1108 * {@link android.content.pm.PackageManager#getApplicationInfo(String, int)}. 1109 * @return {@link ImeCommand} object that can be passed to 1110 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1111 * wait until this event is handled by {@link MockIme}. 1112 */ 1113 @NonNull callGetApplicationInfo(@onNull String packageName, int flags)1114 public ImeCommand callGetApplicationInfo(@NonNull String packageName, int flags) { 1115 final Bundle params = new Bundle(); 1116 params.putString("packageName", packageName); 1117 params.putInt("flags", flags); 1118 return callCommandInternal("getApplicationInfo", params); 1119 } 1120 1121 @NonNull callGetDisplayId()1122 public ImeCommand callGetDisplayId() { 1123 final Bundle params = new Bundle(); 1124 return callCommandInternal("getDisplayId", params); 1125 } 1126 1127 /** 1128 * Verifies {@code InputMethodService.getLayoutInflater().getContext()} is equal to 1129 * {@code InputMethodService.this}. 1130 * 1131 * @return {@link ImeCommand} object that can be passed to 1132 * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to 1133 * wait until this event is handled by {@link MockIme} 1134 */ 1135 @NonNull verifyLayoutInflaterContext()1136 public ImeCommand verifyLayoutInflaterContext() { 1137 final Bundle params = new Bundle(); 1138 return callCommandInternal("verifyLayoutInflaterContext", params); 1139 } 1140 1141 @NonNull callSetHeight(int height)1142 public ImeCommand callSetHeight(int height) { 1143 final Bundle params = new Bundle(); 1144 params.putInt("height", height); 1145 return callCommandInternal("setHeight", params); 1146 } 1147 1148 @NonNull callSetInlineSuggestionsExtras(@onNull Bundle bundle)1149 public ImeCommand callSetInlineSuggestionsExtras(@NonNull Bundle bundle) { 1150 return callCommandInternal("setInlineSuggestionsExtras", bundle); 1151 } 1152 1153 @NonNull callVerifyGetDisplay()1154 public ImeCommand callVerifyGetDisplay() { 1155 return callCommandInternal("verifyGetDisplay", new Bundle()); 1156 } 1157 1158 @NonNull callVerifyGetWindowManager()1159 public ImeCommand callVerifyGetWindowManager() { 1160 return callCommandInternal("verifyGetWindowManager", new Bundle()); 1161 } 1162 1163 @NonNull callVerifyGetViewConfiguration()1164 public ImeCommand callVerifyGetViewConfiguration() { 1165 return callCommandInternal("verifyGetViewConfiguration", new Bundle()); 1166 } 1167 1168 @NonNull callVerifyGetGestureDetector()1169 public ImeCommand callVerifyGetGestureDetector() { 1170 return callCommandInternal("verifyGetGestureDetector", new Bundle()); 1171 } 1172 1173 @NonNull callVerifyGetWindowManagerOnDisplayContext()1174 public ImeCommand callVerifyGetWindowManagerOnDisplayContext() { 1175 return callCommandInternal("verifyGetWindowManagerOnDisplayContext", new Bundle()); 1176 } 1177 1178 @NonNull callVerifyGetViewConfigurationOnDisplayContext()1179 public ImeCommand callVerifyGetViewConfigurationOnDisplayContext() { 1180 return callCommandInternal("verifyGetViewConfigurationOnDisplayContext", new Bundle()); 1181 } 1182 1183 @NonNull callVerifyGetGestureDetectorOnDisplayContext()1184 public ImeCommand callVerifyGetGestureDetectorOnDisplayContext() { 1185 return callCommandInternal("verifyGetGestureDetectorOnDisplayContext", new Bundle()); 1186 } 1187 } 1188