1 /* 2 * Copyright (C) 2022 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 android.view.inputmethod; 18 19 import android.Manifest; 20 import android.annotation.AnyThread; 21 import android.annotation.DurationMillisLong; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.RequiresNoPermission; 25 import android.annotation.RequiresPermission; 26 import android.annotation.UserIdInt; 27 import android.content.Context; 28 import android.os.Binder; 29 import android.os.IBinder; 30 import android.os.RemoteException; 31 import android.os.ResultReceiver; 32 import android.os.ServiceManager; 33 import android.view.WindowManager; 34 import android.window.ImeOnBackInvokedDispatcher; 35 36 import com.android.internal.inputmethod.DirectBootAwareness; 37 import com.android.internal.inputmethod.IImeTracker; 38 import com.android.internal.inputmethod.IInputMethodClient; 39 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; 40 import com.android.internal.inputmethod.IRemoteInputConnection; 41 import com.android.internal.inputmethod.InputBindResult; 42 import com.android.internal.inputmethod.SoftInputShowHideReason; 43 import com.android.internal.inputmethod.StartInputFlags; 44 import com.android.internal.inputmethod.StartInputReason; 45 import com.android.internal.view.IInputMethodManager; 46 47 import java.util.ArrayList; 48 import java.util.List; 49 import java.util.function.Consumer; 50 51 /** 52 * A global wrapper to directly invoke {@link IInputMethodManager} IPCs. 53 * 54 * <p>All public static methods are guaranteed to be thread-safe.</p> 55 * 56 * <p>All public methods are guaranteed to do nothing when {@link IInputMethodManager} is 57 * unavailable.</p> 58 * 59 * <p>If you want to use any of this method outside of {@code android.view.inputmethod}, create 60 * a wrapper method in {@link InputMethodManagerGlobal} instead of making this class public.</p> 61 */ 62 final class IInputMethodManagerGlobalInvoker { 63 @Nullable 64 private static volatile IInputMethodManager sServiceCache = null; 65 66 @Nullable 67 private static volatile IImeTracker sTrackerServiceCache = null; 68 69 /** 70 * @return {@code true} if {@link IInputMethodManager} is available. 71 */ 72 @AnyThread isAvailable()73 static boolean isAvailable() { 74 return getService() != null; 75 } 76 77 @AnyThread 78 @Nullable getService()79 static IInputMethodManager getService() { 80 IInputMethodManager service = sServiceCache; 81 if (service == null) { 82 if (InputMethodManager.isInEditModeInternal()) { 83 return null; 84 } 85 service = IInputMethodManager.Stub.asInterface( 86 ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); 87 if (service == null) { 88 return null; 89 } 90 sServiceCache = service; 91 } 92 return service; 93 } 94 95 @AnyThread handleRemoteExceptionOrRethrow(@onNull RemoteException e, @Nullable Consumer<RemoteException> exceptionHandler)96 private static void handleRemoteExceptionOrRethrow(@NonNull RemoteException e, 97 @Nullable Consumer<RemoteException> exceptionHandler) { 98 if (exceptionHandler != null) { 99 exceptionHandler.accept(e); 100 } else { 101 throw e.rethrowFromSystemServer(); 102 } 103 } 104 105 /** 106 * Invokes {@link IInputMethodManager#startProtoDump(byte[], int, String)}. 107 * 108 * @param protoDump client or service side information to be stored by the server 109 * @param source where the information is coming from, refer to 110 * {@link com.android.internal.inputmethod.ImeTracing#IME_TRACING_FROM_CLIENT} and 111 * {@link com.android.internal.inputmethod.ImeTracing#IME_TRACING_FROM_IMS} 112 * @param where where the information is coming from. 113 * @param exceptionHandler an optional {@link RemoteException} handler. 114 */ 115 @AnyThread 116 @RequiresNoPermission startProtoDump(byte[] protoDump, int source, String where, @Nullable Consumer<RemoteException> exceptionHandler)117 static void startProtoDump(byte[] protoDump, int source, String where, 118 @Nullable Consumer<RemoteException> exceptionHandler) { 119 final IInputMethodManager service = getService(); 120 if (service == null) { 121 return; 122 } 123 try { 124 service.startProtoDump(protoDump, source, where); 125 } catch (RemoteException e) { 126 handleRemoteExceptionOrRethrow(e, exceptionHandler); 127 } 128 } 129 130 /** 131 * Invokes {@link IInputMethodManager#startImeTrace()}. 132 * 133 * @param exceptionHandler an optional {@link RemoteException} handler. 134 */ 135 @AnyThread 136 @RequiresPermission(Manifest.permission.CONTROL_UI_TRACING) startImeTrace(@ullable Consumer<RemoteException> exceptionHandler)137 static void startImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { 138 final IInputMethodManager service = getService(); 139 if (service == null) { 140 return; 141 } 142 try { 143 service.startImeTrace(); 144 } catch (RemoteException e) { 145 handleRemoteExceptionOrRethrow(e, exceptionHandler); 146 } 147 } 148 149 /** 150 * Invokes {@link IInputMethodManager#stopImeTrace()}. 151 * 152 * @param exceptionHandler an optional {@link RemoteException} handler. 153 */ 154 @AnyThread 155 @RequiresPermission(Manifest.permission.CONTROL_UI_TRACING) stopImeTrace(@ullable Consumer<RemoteException> exceptionHandler)156 static void stopImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { 157 final IInputMethodManager service = getService(); 158 if (service == null) { 159 return; 160 } 161 try { 162 service.stopImeTrace(); 163 } catch (RemoteException e) { 164 handleRemoteExceptionOrRethrow(e, exceptionHandler); 165 } 166 } 167 168 /** 169 * Invokes {@link IInputMethodManager#isImeTraceEnabled()}. 170 * 171 * @return The return value of {@link IInputMethodManager#isImeTraceEnabled()}. 172 */ 173 @AnyThread 174 @RequiresNoPermission isImeTraceEnabled()175 static boolean isImeTraceEnabled() { 176 final IInputMethodManager service = getService(); 177 if (service == null) { 178 return false; 179 } 180 try { 181 return service.isImeTraceEnabled(); 182 } catch (RemoteException e) { 183 throw e.rethrowFromSystemServer(); 184 } 185 } 186 187 /** 188 * Invokes {@link IInputMethodManager#removeImeSurface()} 189 */ 190 @AnyThread 191 @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW) removeImeSurface(@ullable Consumer<RemoteException> exceptionHandler)192 static void removeImeSurface(@Nullable Consumer<RemoteException> exceptionHandler) { 193 final IInputMethodManager service = getService(); 194 if (service == null) { 195 return; 196 } 197 try { 198 service.removeImeSurface(); 199 } catch (RemoteException e) { 200 handleRemoteExceptionOrRethrow(e, exceptionHandler); 201 } 202 } 203 204 @AnyThread addClient(@onNull IInputMethodClient client, @NonNull IRemoteInputConnection fallbackInputConnection, int untrustedDisplayId)205 static void addClient(@NonNull IInputMethodClient client, 206 @NonNull IRemoteInputConnection fallbackInputConnection, int untrustedDisplayId) { 207 final IInputMethodManager service = getService(); 208 if (service == null) { 209 return; 210 } 211 try { 212 service.addClient(client, fallbackInputConnection, untrustedDisplayId); 213 } catch (RemoteException e) { 214 throw e.rethrowFromSystemServer(); 215 } 216 } 217 218 @AnyThread 219 @Nullable 220 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) getCurrentInputMethodInfoAsUser(@serIdInt int userId)221 static InputMethodInfo getCurrentInputMethodInfoAsUser(@UserIdInt int userId) { 222 final IInputMethodManager service = getService(); 223 if (service == null) { 224 return null; 225 } 226 try { 227 return service.getCurrentInputMethodInfoAsUser(userId); 228 } catch (RemoteException e) { 229 throw e.rethrowFromSystemServer(); 230 } 231 } 232 233 @AnyThread 234 @NonNull 235 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) getInputMethodList(@serIdInt int userId, @DirectBootAwareness int directBootAwareness)236 static List<InputMethodInfo> getInputMethodList(@UserIdInt int userId, 237 @DirectBootAwareness int directBootAwareness) { 238 final IInputMethodManager service = getService(); 239 if (service == null) { 240 return new ArrayList<>(); 241 } 242 try { 243 return service.getInputMethodList(userId, directBootAwareness); 244 } catch (RemoteException e) { 245 throw e.rethrowFromSystemServer(); 246 } 247 } 248 249 @AnyThread 250 @NonNull 251 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) getEnabledInputMethodList(@serIdInt int userId)252 static List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) { 253 final IInputMethodManager service = getService(); 254 if (service == null) { 255 return new ArrayList<>(); 256 } 257 try { 258 return service.getEnabledInputMethodList(userId); 259 } catch (RemoteException e) { 260 throw e.rethrowFromSystemServer(); 261 } 262 } 263 264 @AnyThread 265 @NonNull 266 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) getEnabledInputMethodSubtypeList(@ullable String imiId, boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId)267 static List<InputMethodSubtype> getEnabledInputMethodSubtypeList(@Nullable String imiId, 268 boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) { 269 final IInputMethodManager service = getService(); 270 if (service == null) { 271 return new ArrayList<>(); 272 } 273 try { 274 return service.getEnabledInputMethodSubtypeList(imiId, 275 allowsImplicitlyEnabledSubtypes, userId); 276 } catch (RemoteException e) { 277 throw e.rethrowFromSystemServer(); 278 } 279 } 280 281 @AnyThread 282 @Nullable 283 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) getLastInputMethodSubtype(@serIdInt int userId)284 static InputMethodSubtype getLastInputMethodSubtype(@UserIdInt int userId) { 285 final IInputMethodManager service = getService(); 286 if (service == null) { 287 return null; 288 } 289 try { 290 return service.getLastInputMethodSubtype(userId); 291 } catch (RemoteException e) { 292 throw e.rethrowFromSystemServer(); 293 } 294 } 295 296 @AnyThread showSoftInput(@onNull IInputMethodClient client, @Nullable IBinder windowToken, @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags, int lastClickToolType, @Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason)297 static boolean showSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken, 298 @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags, 299 int lastClickToolType, @Nullable ResultReceiver resultReceiver, 300 @SoftInputShowHideReason int reason) { 301 final IInputMethodManager service = getService(); 302 if (service == null) { 303 return false; 304 } 305 try { 306 return service.showSoftInput(client, windowToken, statsToken, flags, lastClickToolType, 307 resultReceiver, reason); 308 } catch (RemoteException e) { 309 throw e.rethrowFromSystemServer(); 310 } 311 } 312 313 @AnyThread hideSoftInput(@onNull IInputMethodClient client, @Nullable IBinder windowToken, @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags, @Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason)314 static boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken, 315 @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags, 316 @Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { 317 final IInputMethodManager service = getService(); 318 if (service == null) { 319 return false; 320 } 321 try { 322 return service.hideSoftInput(client, windowToken, statsToken, flags, resultReceiver, 323 reason); 324 } catch (RemoteException e) { 325 throw e.rethrowFromSystemServer(); 326 } 327 } 328 329 @AnyThread 330 @NonNull 331 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) startInputOrWindowGainedFocus(@tartInputReason int startInputReason, @NonNull IInputMethodClient client, @Nullable IBinder windowToken, @StartInputFlags int startInputFlags, @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, @WindowManager.LayoutParams.Flags int windowFlags, @Nullable EditorInfo editorInfo, @Nullable IRemoteInputConnection remoteInputConnection, @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection, int unverifiedTargetSdkVersion, @UserIdInt int userId, @NonNull ImeOnBackInvokedDispatcher imeDispatcher)332 static InputBindResult startInputOrWindowGainedFocus(@StartInputReason int startInputReason, 333 @NonNull IInputMethodClient client, @Nullable IBinder windowToken, 334 @StartInputFlags int startInputFlags, 335 @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, 336 @WindowManager.LayoutParams.Flags int windowFlags, @Nullable EditorInfo editorInfo, 337 @Nullable IRemoteInputConnection remoteInputConnection, 338 @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection, 339 int unverifiedTargetSdkVersion, @UserIdInt int userId, 340 @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { 341 final IInputMethodManager service = getService(); 342 if (service == null) { 343 return InputBindResult.NULL; 344 } 345 try { 346 return service.startInputOrWindowGainedFocus(startInputReason, client, windowToken, 347 startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection, 348 remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId, 349 imeDispatcher); 350 } catch (RemoteException e) { 351 throw e.rethrowFromSystemServer(); 352 } 353 } 354 355 @AnyThread showInputMethodPickerFromClient(@onNull IInputMethodClient client, int auxiliarySubtypeMode)356 static void showInputMethodPickerFromClient(@NonNull IInputMethodClient client, 357 int auxiliarySubtypeMode) { 358 final IInputMethodManager service = getService(); 359 if (service == null) { 360 return; 361 } 362 try { 363 service.showInputMethodPickerFromClient(client, auxiliarySubtypeMode); 364 } catch (RemoteException e) { 365 throw e.rethrowFromSystemServer(); 366 } 367 } 368 369 @AnyThread 370 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId)371 static void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) { 372 final IInputMethodManager service = getService(); 373 if (service == null) { 374 return; 375 } 376 try { 377 service.showInputMethodPickerFromSystem(auxiliarySubtypeMode, displayId); 378 } catch (RemoteException e) { 379 throw e.rethrowFromSystemServer(); 380 } 381 } 382 383 @AnyThread 384 @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD) isInputMethodPickerShownForTest()385 static boolean isInputMethodPickerShownForTest() { 386 final IInputMethodManager service = getService(); 387 if (service == null) { 388 return false; 389 } 390 try { 391 return service.isInputMethodPickerShownForTest(); 392 } catch (RemoteException e) { 393 throw e.rethrowFromSystemServer(); 394 } 395 } 396 397 @AnyThread 398 @Nullable 399 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) getCurrentInputMethodSubtype(@serIdInt int userId)400 static InputMethodSubtype getCurrentInputMethodSubtype(@UserIdInt int userId) { 401 final IInputMethodManager service = getService(); 402 if (service == null) { 403 return null; 404 } 405 try { 406 return service.getCurrentInputMethodSubtype(userId); 407 } catch (RemoteException e) { 408 throw e.rethrowFromSystemServer(); 409 } 410 } 411 412 @AnyThread 413 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) setAdditionalInputMethodSubtypes(@onNull String imeId, @NonNull InputMethodSubtype[] subtypes, @UserIdInt int userId)414 static void setAdditionalInputMethodSubtypes(@NonNull String imeId, 415 @NonNull InputMethodSubtype[] subtypes, @UserIdInt int userId) { 416 final IInputMethodManager service = getService(); 417 if (service == null) { 418 return; 419 } 420 try { 421 service.setAdditionalInputMethodSubtypes(imeId, subtypes, userId); 422 } catch (RemoteException e) { 423 throw e.rethrowFromSystemServer(); 424 } 425 } 426 427 @AnyThread 428 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) setExplicitlyEnabledInputMethodSubtypes(@onNull String imeId, @NonNull int[] subtypeHashCodes, @UserIdInt int userId)429 static void setExplicitlyEnabledInputMethodSubtypes(@NonNull String imeId, 430 @NonNull int[] subtypeHashCodes, @UserIdInt int userId) { 431 final IInputMethodManager service = getService(); 432 if (service == null) { 433 return; 434 } 435 try { 436 service.setExplicitlyEnabledInputMethodSubtypes(imeId, subtypeHashCodes, userId); 437 } catch (RemoteException e) { 438 throw e.rethrowFromSystemServer(); 439 } 440 } 441 442 @AnyThread getInputMethodWindowVisibleHeight(@onNull IInputMethodClient client)443 static int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) { 444 final IInputMethodManager service = getService(); 445 if (service == null) { 446 return 0; 447 } 448 try { 449 return service.getInputMethodWindowVisibleHeight(client); 450 } catch (RemoteException e) { 451 throw e.rethrowFromSystemServer(); 452 } 453 } 454 455 @AnyThread reportVirtualDisplayGeometryAsync(@onNull IInputMethodClient client, int childDisplayId, @Nullable float[] matrixValues)456 static void reportVirtualDisplayGeometryAsync(@NonNull IInputMethodClient client, 457 int childDisplayId, @Nullable float[] matrixValues) { 458 final IInputMethodManager service = getService(); 459 if (service == null) { 460 return; 461 } 462 try { 463 service.reportVirtualDisplayGeometryAsync(client, childDisplayId, matrixValues); 464 } catch (RemoteException e) { 465 throw e.rethrowFromSystemServer(); 466 } 467 } 468 469 @AnyThread reportPerceptibleAsync(@onNull IBinder windowToken, boolean perceptible)470 static void reportPerceptibleAsync(@NonNull IBinder windowToken, boolean perceptible) { 471 final IInputMethodManager service = getService(); 472 if (service == null) { 473 return; 474 } 475 try { 476 service.reportPerceptibleAsync(windowToken, perceptible); 477 } catch (RemoteException e) { 478 throw e.rethrowFromSystemServer(); 479 } 480 } 481 482 @AnyThread removeImeSurfaceFromWindowAsync(@onNull IBinder windowToken)483 static void removeImeSurfaceFromWindowAsync(@NonNull IBinder windowToken) { 484 final IInputMethodManager service = getService(); 485 if (service == null) { 486 return; 487 } 488 try { 489 service.removeImeSurfaceFromWindowAsync(windowToken); 490 } catch (RemoteException e) { 491 throw e.rethrowFromSystemServer(); 492 } 493 } 494 495 @AnyThread startStylusHandwriting(@onNull IInputMethodClient client)496 static void startStylusHandwriting(@NonNull IInputMethodClient client) { 497 final IInputMethodManager service = getService(); 498 if (service == null) { 499 return; 500 } 501 try { 502 service.startStylusHandwriting(client); 503 } catch (RemoteException e) { 504 throw e.rethrowFromSystemServer(); 505 } 506 } 507 508 @AnyThread prepareStylusHandwritingDelegation( @onNull IInputMethodClient client, @UserIdInt int userId, @NonNull String delegatePackageName, @NonNull String delegatorPackageName)509 static void prepareStylusHandwritingDelegation( 510 @NonNull IInputMethodClient client, 511 @UserIdInt int userId, 512 @NonNull String delegatePackageName, 513 @NonNull String delegatorPackageName) { 514 final IInputMethodManager service = getService(); 515 if (service == null) { 516 return; 517 } 518 try { 519 service.prepareStylusHandwritingDelegation( 520 client, userId, delegatePackageName, delegatorPackageName); 521 } catch (RemoteException e) { 522 throw e.rethrowFromSystemServer(); 523 } 524 } 525 526 @AnyThread acceptStylusHandwritingDelegation( @onNull IInputMethodClient client, @UserIdInt int userId, @NonNull String delegatePackageName, @NonNull String delegatorPackageName)527 static boolean acceptStylusHandwritingDelegation( 528 @NonNull IInputMethodClient client, 529 @UserIdInt int userId, 530 @NonNull String delegatePackageName, 531 @NonNull String delegatorPackageName) { 532 final IInputMethodManager service = getService(); 533 if (service == null) { 534 return false; 535 } 536 try { 537 return service.acceptStylusHandwritingDelegation( 538 client, userId, delegatePackageName, delegatorPackageName); 539 } catch (RemoteException e) { 540 throw e.rethrowFromSystemServer(); 541 } 542 } 543 544 @AnyThread 545 @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true) isStylusHandwritingAvailableAsUser(@serIdInt int userId)546 static boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId) { 547 final IInputMethodManager service = getService(); 548 if (service == null) { 549 return false; 550 } 551 try { 552 return service.isStylusHandwritingAvailableAsUser(userId); 553 } catch (RemoteException e) { 554 throw e.rethrowFromSystemServer(); 555 } 556 } 557 558 @AnyThread 559 @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD) addVirtualStylusIdForTestSession(IInputMethodClient client)560 static void addVirtualStylusIdForTestSession(IInputMethodClient client) { 561 final IInputMethodManager service = getService(); 562 if (service == null) { 563 return; 564 } 565 try { 566 service.addVirtualStylusIdForTestSession(client); 567 } catch (RemoteException e) { 568 throw e.rethrowFromSystemServer(); 569 } 570 } 571 572 @AnyThread 573 @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD) setStylusWindowIdleTimeoutForTest( IInputMethodClient client, @DurationMillisLong long timeout)574 static void setStylusWindowIdleTimeoutForTest( 575 IInputMethodClient client, @DurationMillisLong long timeout) { 576 final IInputMethodManager service = getService(); 577 if (service == null) { 578 return; 579 } 580 try { 581 service.setStylusWindowIdleTimeoutForTest(client, timeout); 582 } catch (RemoteException e) { 583 throw e.rethrowFromSystemServer(); 584 } 585 } 586 587 /** @see com.android.server.inputmethod.ImeTrackerService#onRequestShow */ 588 @AnyThread 589 @NonNull onRequestShow(@onNull String tag, int uid, @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason)590 static ImeTracker.Token onRequestShow(@NonNull String tag, int uid, 591 @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) { 592 final IImeTracker service = getImeTrackerService(); 593 if (service == null) { 594 // Create token with "fake" binder if the service was not found. 595 return new ImeTracker.Token(new Binder(), tag); 596 } 597 try { 598 return service.onRequestShow(tag, uid, origin, reason); 599 } catch (RemoteException e) { 600 throw e.rethrowFromSystemServer(); 601 } 602 } 603 604 /** @see com.android.server.inputmethod.ImeTrackerService#onRequestHide */ 605 @AnyThread 606 @NonNull onRequestHide(@onNull String tag, int uid, @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason)607 static ImeTracker.Token onRequestHide(@NonNull String tag, int uid, 608 @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) { 609 final IImeTracker service = getImeTrackerService(); 610 if (service == null) { 611 // Create token with "fake" binder if the service was not found. 612 return new ImeTracker.Token(new Binder(), tag); 613 } 614 try { 615 return service.onRequestHide(tag, uid, origin, reason); 616 } catch (RemoteException e) { 617 throw e.rethrowFromSystemServer(); 618 } 619 } 620 621 /** @see com.android.server.inputmethod.ImeTrackerService#onProgress */ 622 @AnyThread onProgress(@onNull IBinder binder, @ImeTracker.Phase int phase)623 static void onProgress(@NonNull IBinder binder, @ImeTracker.Phase int phase) { 624 final IImeTracker service = getImeTrackerService(); 625 if (service == null) { 626 return; 627 } 628 try { 629 service.onProgress(binder, phase); 630 } catch (RemoteException e) { 631 throw e.rethrowFromSystemServer(); 632 } 633 } 634 635 /** @see com.android.server.inputmethod.ImeTrackerService#onFailed */ 636 @AnyThread onFailed(@onNull ImeTracker.Token statsToken, @ImeTracker.Phase int phase)637 static void onFailed(@NonNull ImeTracker.Token statsToken, @ImeTracker.Phase int phase) { 638 final IImeTracker service = getImeTrackerService(); 639 if (service == null) { 640 return; 641 } 642 try { 643 service.onFailed(statsToken, phase); 644 } catch (RemoteException e) { 645 throw e.rethrowFromSystemServer(); 646 } 647 } 648 649 /** @see com.android.server.inputmethod.ImeTrackerService#onCancelled */ 650 @AnyThread onCancelled(@onNull ImeTracker.Token statsToken, @ImeTracker.Phase int phase)651 static void onCancelled(@NonNull ImeTracker.Token statsToken, @ImeTracker.Phase int phase) { 652 final IImeTracker service = getImeTrackerService(); 653 if (service == null) { 654 return; 655 } 656 try { 657 service.onCancelled(statsToken, phase); 658 } catch (RemoteException e) { 659 throw e.rethrowFromSystemServer(); 660 } 661 } 662 663 /** @see com.android.server.inputmethod.ImeTrackerService#onShown */ 664 @AnyThread onShown(@onNull ImeTracker.Token statsToken)665 static void onShown(@NonNull ImeTracker.Token statsToken) { 666 final IImeTracker service = getImeTrackerService(); 667 if (service == null) { 668 return; 669 } 670 try { 671 service.onShown(statsToken); 672 } catch (RemoteException e) { 673 throw e.rethrowFromSystemServer(); 674 } 675 } 676 677 /** @see com.android.server.inputmethod.ImeTrackerService#onHidden */ 678 @AnyThread onHidden(@onNull ImeTracker.Token statsToken)679 static void onHidden(@NonNull ImeTracker.Token statsToken) { 680 final IImeTracker service = getImeTrackerService(); 681 if (service == null) { 682 return; 683 } 684 try { 685 service.onHidden(statsToken); 686 } catch (RemoteException e) { 687 throw e.rethrowFromSystemServer(); 688 } 689 } 690 691 /** @see com.android.server.inputmethod.ImeTrackerService#hasPendingImeVisibilityRequests */ 692 @AnyThread 693 @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD) hasPendingImeVisibilityRequests()694 static boolean hasPendingImeVisibilityRequests() { 695 final var service = getImeTrackerService(); 696 if (service == null) { 697 return true; 698 } 699 try { 700 return service.hasPendingImeVisibilityRequests(); 701 } catch (RemoteException e) { 702 throw e.rethrowFromSystemServer(); 703 } 704 } 705 706 @AnyThread 707 @Nullable getImeTrackerService()708 private static IImeTracker getImeTrackerService() { 709 var trackerService = sTrackerServiceCache; 710 if (trackerService == null) { 711 final var service = getService(); 712 if (service == null) { 713 return null; 714 } 715 716 try { 717 trackerService = service.getImeTrackerService(); 718 if (trackerService == null) { 719 return null; 720 } 721 722 sTrackerServiceCache = trackerService; 723 } catch (RemoteException e) { 724 throw e.rethrowFromSystemServer(); 725 } 726 } 727 return trackerService; 728 } 729 } 730