1 /* 2 * Copyright (C) 2013 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.app; 18 19 import static android.view.Display.DEFAULT_DISPLAY; 20 21 import android.accessibilityservice.AccessibilityServiceInfo; 22 import android.accessibilityservice.IAccessibilityServiceClient; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.UserIdInt; 26 import android.companion.virtual.VirtualDeviceManager; 27 import android.compat.annotation.UnsupportedAppUsage; 28 import android.content.Context; 29 import android.graphics.Rect; 30 import android.hardware.input.InputManager; 31 import android.hardware.input.InputManagerGlobal; 32 import android.os.Binder; 33 import android.os.Build; 34 import android.os.IBinder; 35 import android.os.ParcelFileDescriptor; 36 import android.os.Process; 37 import android.os.RemoteException; 38 import android.os.ServiceManager; 39 import android.os.UserHandle; 40 import android.permission.IPermissionManager; 41 import android.util.Log; 42 import android.view.IWindowManager; 43 import android.view.InputDevice; 44 import android.view.InputEvent; 45 import android.view.KeyEvent; 46 import android.view.MotionEvent; 47 import android.view.SurfaceControl; 48 import android.view.WindowAnimationFrameStats; 49 import android.view.WindowContentFrameStats; 50 import android.view.accessibility.AccessibilityEvent; 51 import android.view.accessibility.IAccessibilityManager; 52 import android.window.ScreenCapture; 53 import android.window.ScreenCapture.CaptureArgs; 54 55 import libcore.io.IoUtils; 56 57 import java.io.FileInputStream; 58 import java.io.FileOutputStream; 59 import java.io.IOException; 60 import java.io.InputStream; 61 import java.io.OutputStream; 62 import java.util.List; 63 64 /** 65 * This is a remote object that is passed from the shell to an instrumentation 66 * for enabling access to privileged operations which the shell can do and the 67 * instrumentation cannot. These privileged operations are needed for implementing 68 * a {@link UiAutomation} that enables across application testing by simulating 69 * user actions and performing screen introspection. 70 * 71 * @hide 72 */ 73 public final class UiAutomationConnection extends IUiAutomationConnection.Stub { 74 75 private static final String TAG = "UiAutomationConnection"; 76 77 private static final int INITIAL_FROZEN_ROTATION_UNSPECIFIED = -1; 78 79 private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface( 80 ServiceManager.getService(Service.WINDOW_SERVICE)); 81 82 private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub 83 .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE)); 84 85 private final IPermissionManager mPermissionManager = IPermissionManager.Stub 86 .asInterface(ServiceManager.getService("permissionmgr")); 87 88 private final IActivityManager mActivityManager = IActivityManager.Stub 89 .asInterface(ServiceManager.getService("activity")); 90 91 private final Object mLock = new Object(); 92 93 private final Binder mToken = new Binder(); 94 95 private int mInitialFrozenRotation = INITIAL_FROZEN_ROTATION_UNSPECIFIED; 96 97 private IAccessibilityServiceClient mClient; 98 99 private boolean mIsShutdown; 100 101 private int mOwningUid; 102 103 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) UiAutomationConnection()104 public UiAutomationConnection() { 105 Log.d(TAG, "Created on user " + Process.myUserHandle()); 106 } 107 108 @Override connect(IAccessibilityServiceClient client, int flags)109 public void connect(IAccessibilityServiceClient client, int flags) { 110 if (client == null) { 111 throw new IllegalArgumentException("Client cannot be null!"); 112 } 113 synchronized (mLock) { 114 throwIfShutdownLocked(); 115 if (isConnectedLocked()) { 116 throw new IllegalStateException("Already connected."); 117 } 118 mOwningUid = Binder.getCallingUid(); 119 registerUiTestAutomationServiceLocked(client, 120 Binder.getCallingUserHandle().getIdentifier(), flags); 121 storeRotationStateLocked(); 122 } 123 } 124 125 @Override disconnect()126 public void disconnect() { 127 synchronized (mLock) { 128 throwIfCalledByNotTrustedUidLocked(); 129 throwIfShutdownLocked(); 130 if (!isConnectedLocked()) { 131 throw new IllegalStateException("Already disconnected."); 132 } 133 mOwningUid = -1; 134 unregisterUiTestAutomationServiceLocked(); 135 restoreRotationStateLocked(); 136 } 137 } 138 139 @Override injectInputEvent(InputEvent event, boolean sync, boolean waitForAnimations)140 public boolean injectInputEvent(InputEvent event, boolean sync, boolean waitForAnimations) { 141 synchronized (mLock) { 142 throwIfCalledByNotTrustedUidLocked(); 143 throwIfShutdownLocked(); 144 throwIfNotConnectedLocked(); 145 } 146 147 final boolean syncTransactionsBefore; 148 final boolean syncTransactionsAfter; 149 if (event instanceof KeyEvent) { 150 KeyEvent keyEvent = (KeyEvent) event; 151 syncTransactionsBefore = keyEvent.getAction() == KeyEvent.ACTION_DOWN; 152 syncTransactionsAfter = keyEvent.getAction() == KeyEvent.ACTION_UP; 153 } else { 154 MotionEvent motionEvent = (MotionEvent) event; 155 syncTransactionsBefore = motionEvent.getAction() == MotionEvent.ACTION_DOWN 156 || motionEvent.isFromSource(InputDevice.SOURCE_MOUSE); 157 syncTransactionsAfter = motionEvent.getAction() == MotionEvent.ACTION_UP; 158 } 159 160 final long identity = Binder.clearCallingIdentity(); 161 try { 162 if (syncTransactionsBefore) { 163 mWindowManager.syncInputTransactions(waitForAnimations); 164 } 165 166 final boolean result = InputManagerGlobal.getInstance().injectInputEvent(event, 167 sync ? InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH 168 : InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 169 170 if (syncTransactionsAfter) { 171 mWindowManager.syncInputTransactions(waitForAnimations); 172 } 173 return result; 174 } catch (RemoteException e) { 175 e.rethrowFromSystemServer(); 176 } finally { 177 Binder.restoreCallingIdentity(identity); 178 } 179 return false; 180 } 181 182 @Override injectInputEventToInputFilter(InputEvent event)183 public void injectInputEventToInputFilter(InputEvent event) throws RemoteException { 184 synchronized (mLock) { 185 throwIfCalledByNotTrustedUidLocked(); 186 throwIfShutdownLocked(); 187 throwIfNotConnectedLocked(); 188 } 189 mAccessibilityManager.injectInputEventToInputFilter(event); 190 } 191 192 @Override syncInputTransactions(boolean waitForAnimations)193 public void syncInputTransactions(boolean waitForAnimations) { 194 synchronized (mLock) { 195 throwIfCalledByNotTrustedUidLocked(); 196 throwIfShutdownLocked(); 197 throwIfNotConnectedLocked(); 198 } 199 200 try { 201 mWindowManager.syncInputTransactions(waitForAnimations); 202 } catch (RemoteException e) { 203 } 204 } 205 206 @Override setRotation(int rotation)207 public boolean setRotation(int rotation) { 208 synchronized (mLock) { 209 throwIfCalledByNotTrustedUidLocked(); 210 throwIfShutdownLocked(); 211 throwIfNotConnectedLocked(); 212 } 213 final long identity = Binder.clearCallingIdentity(); 214 try { 215 if (rotation == UiAutomation.ROTATION_UNFREEZE) { 216 mWindowManager.thawRotation(/* caller= */ "UiAutomationConnection#setRotation"); 217 } else { 218 mWindowManager.freezeRotation(rotation, 219 /* caller= */ "UiAutomationConnection#setRotation"); 220 } 221 return true; 222 } catch (RemoteException re) { 223 /* ignore */ 224 } finally { 225 Binder.restoreCallingIdentity(identity); 226 } 227 return false; 228 } 229 230 @Override takeScreenshot(Rect crop, ScreenCapture.ScreenCaptureListener listener)231 public boolean takeScreenshot(Rect crop, ScreenCapture.ScreenCaptureListener listener) { 232 synchronized (mLock) { 233 throwIfCalledByNotTrustedUidLocked(); 234 throwIfShutdownLocked(); 235 throwIfNotConnectedLocked(); 236 } 237 238 final long identity = Binder.clearCallingIdentity(); 239 try { 240 final CaptureArgs captureArgs = new CaptureArgs.Builder<>() 241 .setSourceCrop(crop) 242 .build(); 243 mWindowManager.captureDisplay(DEFAULT_DISPLAY, captureArgs, listener); 244 } catch (RemoteException re) { 245 re.rethrowAsRuntimeException(); 246 } finally { 247 Binder.restoreCallingIdentity(identity); 248 } 249 250 return true; 251 } 252 253 @Nullable 254 @Override takeSurfaceControlScreenshot(@onNull SurfaceControl surfaceControl, ScreenCapture.ScreenCaptureListener listener)255 public boolean takeSurfaceControlScreenshot(@NonNull SurfaceControl surfaceControl, 256 ScreenCapture.ScreenCaptureListener listener) { 257 synchronized (mLock) { 258 throwIfCalledByNotTrustedUidLocked(); 259 throwIfShutdownLocked(); 260 throwIfNotConnectedLocked(); 261 } 262 263 final long identity = Binder.clearCallingIdentity(); 264 try { 265 ScreenCapture.LayerCaptureArgs args = 266 new ScreenCapture.LayerCaptureArgs.Builder(surfaceControl) 267 .setChildrenOnly(false) 268 .build(); 269 int status = ScreenCapture.captureLayers(args, listener); 270 271 if (status != 0) { 272 return false; 273 } 274 } finally { 275 Binder.restoreCallingIdentity(identity); 276 } 277 278 return true; 279 } 280 281 @Override clearWindowContentFrameStats(int windowId)282 public boolean clearWindowContentFrameStats(int windowId) throws RemoteException { 283 synchronized (mLock) { 284 throwIfCalledByNotTrustedUidLocked(); 285 throwIfShutdownLocked(); 286 throwIfNotConnectedLocked(); 287 } 288 int callingUserId = UserHandle.getCallingUserId(); 289 final long identity = Binder.clearCallingIdentity(); 290 try { 291 IBinder token = mAccessibilityManager.getWindowToken(windowId, callingUserId); 292 if (token == null) { 293 return false; 294 } 295 return mWindowManager.clearWindowContentFrameStats(token); 296 } finally { 297 Binder.restoreCallingIdentity(identity); 298 } 299 } 300 301 @Override getWindowContentFrameStats(int windowId)302 public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException { 303 synchronized (mLock) { 304 throwIfCalledByNotTrustedUidLocked(); 305 throwIfShutdownLocked(); 306 throwIfNotConnectedLocked(); 307 } 308 int callingUserId = UserHandle.getCallingUserId(); 309 final long identity = Binder.clearCallingIdentity(); 310 try { 311 IBinder token = mAccessibilityManager.getWindowToken(windowId, callingUserId); 312 if (token == null) { 313 return null; 314 } 315 return mWindowManager.getWindowContentFrameStats(token); 316 } finally { 317 Binder.restoreCallingIdentity(identity); 318 } 319 } 320 321 @Override clearWindowAnimationFrameStats()322 public void clearWindowAnimationFrameStats() { 323 synchronized (mLock) { 324 throwIfCalledByNotTrustedUidLocked(); 325 throwIfShutdownLocked(); 326 throwIfNotConnectedLocked(); 327 } 328 final long identity = Binder.clearCallingIdentity(); 329 try { 330 SurfaceControl.clearAnimationFrameStats(); 331 } finally { 332 Binder.restoreCallingIdentity(identity); 333 } 334 } 335 336 @Override getWindowAnimationFrameStats()337 public WindowAnimationFrameStats getWindowAnimationFrameStats() { 338 synchronized (mLock) { 339 throwIfCalledByNotTrustedUidLocked(); 340 throwIfShutdownLocked(); 341 throwIfNotConnectedLocked(); 342 } 343 final long identity = Binder.clearCallingIdentity(); 344 try { 345 WindowAnimationFrameStats stats = new WindowAnimationFrameStats(); 346 SurfaceControl.getAnimationFrameStats(stats); 347 return stats; 348 } finally { 349 Binder.restoreCallingIdentity(identity); 350 } 351 } 352 353 /** 354 * Grants permission for the {@link Context#DEVICE_ID_DEFAULT default device} 355 */ 356 @Override grantRuntimePermission(String packageName, String permission, int userId)357 public void grantRuntimePermission(String packageName, String permission, int userId) 358 throws RemoteException { 359 synchronized (mLock) { 360 throwIfCalledByNotTrustedUidLocked(); 361 throwIfShutdownLocked(); 362 throwIfNotConnectedLocked(); 363 } 364 final long identity = Binder.clearCallingIdentity(); 365 try { 366 mPermissionManager.grantRuntimePermission(packageName, permission, 367 VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, userId); 368 } finally { 369 Binder.restoreCallingIdentity(identity); 370 } 371 } 372 373 /** 374 * Revokes permission for the {@link Context#DEVICE_ID_DEFAULT default device} 375 */ 376 @Override revokeRuntimePermission(String packageName, String permission, int userId)377 public void revokeRuntimePermission(String packageName, String permission, int userId) 378 throws RemoteException { 379 synchronized (mLock) { 380 throwIfCalledByNotTrustedUidLocked(); 381 throwIfShutdownLocked(); 382 throwIfNotConnectedLocked(); 383 } 384 final long identity = Binder.clearCallingIdentity(); 385 try { 386 mPermissionManager.revokeRuntimePermission(packageName, permission, 387 VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, userId, null); 388 } finally { 389 Binder.restoreCallingIdentity(identity); 390 } 391 } 392 393 @Override adoptShellPermissionIdentity(int uid, @Nullable String[] permissions)394 public void adoptShellPermissionIdentity(int uid, @Nullable String[] permissions) 395 throws RemoteException { 396 synchronized (mLock) { 397 throwIfCalledByNotTrustedUidLocked(); 398 throwIfShutdownLocked(); 399 throwIfNotConnectedLocked(); 400 } 401 final long identity = Binder.clearCallingIdentity(); 402 try { 403 mActivityManager.startDelegateShellPermissionIdentity(uid, permissions); 404 } finally { 405 Binder.restoreCallingIdentity(identity); 406 } 407 } 408 409 @Override dropShellPermissionIdentity()410 public void dropShellPermissionIdentity() throws RemoteException { 411 synchronized (mLock) { 412 throwIfCalledByNotTrustedUidLocked(); 413 throwIfShutdownLocked(); 414 throwIfNotConnectedLocked(); 415 } 416 final long identity = Binder.clearCallingIdentity(); 417 try { 418 mActivityManager.stopDelegateShellPermissionIdentity(); 419 } finally { 420 Binder.restoreCallingIdentity(identity); 421 } 422 } 423 424 @Override 425 @Nullable getAdoptedShellPermissions()426 public List<String> getAdoptedShellPermissions() throws RemoteException { 427 synchronized (mLock) { 428 throwIfCalledByNotTrustedUidLocked(); 429 throwIfShutdownLocked(); 430 throwIfNotConnectedLocked(); 431 } 432 final long identity = Binder.clearCallingIdentity(); 433 try { 434 return mActivityManager.getDelegatedShellPermissions(); 435 } finally { 436 Binder.restoreCallingIdentity(identity); 437 } 438 } 439 440 @Override addOverridePermissionState(int uid, String permission, int result)441 public void addOverridePermissionState(int uid, String permission, int result) 442 throws RemoteException { 443 synchronized (mLock) { 444 throwIfCalledByNotTrustedUidLocked(); 445 throwIfShutdownLocked(); 446 throwIfNotConnectedLocked(); 447 } 448 final int callingUid = Binder.getCallingUid(); 449 final long identity = Binder.clearCallingIdentity(); 450 try { 451 mActivityManager.addOverridePermissionState(callingUid, uid, permission, result); 452 } finally { 453 Binder.restoreCallingIdentity(identity); 454 } 455 } 456 457 @Override removeOverridePermissionState(int uid, String permission)458 public void removeOverridePermissionState(int uid, String permission) throws RemoteException { 459 synchronized (mLock) { 460 throwIfCalledByNotTrustedUidLocked(); 461 throwIfShutdownLocked(); 462 throwIfNotConnectedLocked(); 463 } 464 final int callingUid = Binder.getCallingUid(); 465 final long identity = Binder.clearCallingIdentity(); 466 try { 467 mActivityManager.removeOverridePermissionState(callingUid, uid, permission); 468 } finally { 469 Binder.restoreCallingIdentity(identity); 470 } 471 } 472 473 @Override clearOverridePermissionStates(int uid)474 public void clearOverridePermissionStates(int uid) throws RemoteException { 475 synchronized (mLock) { 476 throwIfCalledByNotTrustedUidLocked(); 477 throwIfShutdownLocked(); 478 throwIfNotConnectedLocked(); 479 } 480 final int callingUid = Binder.getCallingUid(); 481 final long identity = Binder.clearCallingIdentity(); 482 try { 483 mActivityManager.clearOverridePermissionStates(callingUid, uid); 484 } finally { 485 Binder.restoreCallingIdentity(identity); 486 } 487 } 488 489 @Override clearAllOverridePermissionStates()490 public void clearAllOverridePermissionStates() throws RemoteException { 491 synchronized (mLock) { 492 throwIfCalledByNotTrustedUidLocked(); 493 throwIfShutdownLocked(); 494 throwIfNotConnectedLocked(); 495 } 496 final int callingUid = Binder.getCallingUid(); 497 final long identity = Binder.clearCallingIdentity(); 498 try { 499 mActivityManager.clearAllOverridePermissionStates(callingUid); 500 } finally { 501 Binder.restoreCallingIdentity(identity); 502 } 503 } 504 505 public class Repeater implements Runnable { 506 // Continuously read readFrom and write back to writeTo until EOF is encountered 507 private final InputStream readFrom; 508 private final OutputStream writeTo; Repeater(InputStream readFrom, OutputStream writeTo)509 public Repeater (InputStream readFrom, OutputStream writeTo) { 510 this.readFrom = readFrom; 511 this.writeTo = writeTo; 512 } 513 @Override run()514 public void run() { 515 try { 516 final byte[] buffer = new byte[8192]; 517 int readByteCount; 518 while (true) { 519 readByteCount = readFrom.read(buffer); 520 if (readByteCount < 0) { 521 break; 522 } 523 writeTo.write(buffer, 0, readByteCount); 524 writeTo.flush(); 525 } 526 } catch (IOException ignored) { 527 } finally { 528 IoUtils.closeQuietly(readFrom); 529 IoUtils.closeQuietly(writeTo); 530 } 531 } 532 } 533 534 @Override executeShellCommand(final String command, final ParcelFileDescriptor sink, final ParcelFileDescriptor source)535 public void executeShellCommand(final String command, final ParcelFileDescriptor sink, 536 final ParcelFileDescriptor source) throws RemoteException { 537 executeShellCommandWithStderr(command, sink, source, null /* stderrSink */); 538 } 539 540 @Override executeShellCommandWithStderr(final String command, final ParcelFileDescriptor sink, final ParcelFileDescriptor source, final ParcelFileDescriptor stderrSink)541 public void executeShellCommandWithStderr(final String command, final ParcelFileDescriptor sink, 542 final ParcelFileDescriptor source, final ParcelFileDescriptor stderrSink) 543 throws RemoteException { 544 synchronized (mLock) { 545 throwIfCalledByNotTrustedUidLocked(); 546 throwIfShutdownLocked(); 547 throwIfNotConnectedLocked(); 548 } 549 final java.lang.Process process; 550 551 try { 552 process = Runtime.getRuntime().exec(command); 553 } catch (IOException exc) { 554 throw new RuntimeException("Error running shell command '" + command + "'", exc); 555 } 556 557 // Read from process and write to pipe 558 final Thread readFromProcess; 559 if (sink != null) { 560 InputStream sink_in = process.getInputStream();; 561 OutputStream sink_out = new FileOutputStream(sink.getFileDescriptor()); 562 563 readFromProcess = new Thread(new Repeater(sink_in, sink_out)); 564 readFromProcess.start(); 565 } else { 566 readFromProcess = null; 567 } 568 569 // Read from pipe and write to process 570 final Thread writeToProcess; 571 if (source != null) { 572 OutputStream source_out = process.getOutputStream(); 573 InputStream source_in = new FileInputStream(source.getFileDescriptor()); 574 575 writeToProcess = new Thread(new Repeater(source_in, source_out)); 576 writeToProcess.start(); 577 } else { 578 writeToProcess = null; 579 } 580 581 // Read from process stderr and write to pipe 582 final Thread readStderrFromProcess; 583 if (stderrSink != null) { 584 InputStream sink_in = process.getErrorStream(); 585 OutputStream sink_out = new FileOutputStream(stderrSink.getFileDescriptor()); 586 587 readStderrFromProcess = new Thread(new Repeater(sink_in, sink_out)); 588 readStderrFromProcess.start(); 589 } else { 590 readStderrFromProcess = null; 591 } 592 593 Thread cleanup = new Thread(new Runnable() { 594 @Override 595 public void run() { 596 try { 597 if (writeToProcess != null) { 598 writeToProcess.join(); 599 } 600 if (readFromProcess != null) { 601 readFromProcess.join(); 602 } 603 if (readStderrFromProcess != null) { 604 readStderrFromProcess.join(); 605 } 606 } catch (InterruptedException exc) { 607 Log.e(TAG, "At least one of the threads was interrupted"); 608 } 609 IoUtils.closeQuietly(sink); 610 IoUtils.closeQuietly(source); 611 IoUtils.closeQuietly(stderrSink); 612 process.destroy(); 613 } 614 }); 615 cleanup.start(); 616 } 617 618 @Override shutdown()619 public void shutdown() { 620 synchronized (mLock) { 621 if (isConnectedLocked()) { 622 throwIfCalledByNotTrustedUidLocked(); 623 } 624 throwIfShutdownLocked(); 625 mIsShutdown = true; 626 if (isConnectedLocked()) { 627 disconnect(); 628 } 629 } 630 } 631 registerUiTestAutomationServiceLocked(IAccessibilityServiceClient client, @UserIdInt int userId, int flags)632 private void registerUiTestAutomationServiceLocked(IAccessibilityServiceClient client, 633 @UserIdInt int userId, int flags) { 634 IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface( 635 ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)); 636 final AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 637 info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; 638 info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; 639 info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 640 | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS 641 | AccessibilityServiceInfo.FLAG_FORCE_DIRECT_BOOT_AWARE; 642 info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 643 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 644 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS); 645 if ((flags & UiAutomation.FLAG_NOT_ACCESSIBILITY_TOOL) == 0) { 646 info.setAccessibilityTool(true); 647 } 648 try { 649 // Calling out with a lock held is fine since if the system 650 // process is gone the client calling in will be killed. 651 manager.registerUiTestAutomationService(mToken, client, info, userId, flags); 652 mClient = client; 653 } catch (RemoteException re) { 654 throw new IllegalStateException("Error while registering UiTestAutomationService for " 655 + "user " + userId + ".", re); 656 } 657 } 658 unregisterUiTestAutomationServiceLocked()659 private void unregisterUiTestAutomationServiceLocked() { 660 IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface( 661 ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)); 662 try { 663 // Calling out with a lock held is fine since if the system 664 // process is gone the client calling in will be killed. 665 manager.unregisterUiTestAutomationService(mClient); 666 mClient = null; 667 } catch (RemoteException re) { 668 throw new IllegalStateException("Error while unregistering UiTestAutomationService", 669 re); 670 } 671 } 672 storeRotationStateLocked()673 private void storeRotationStateLocked() { 674 try { 675 if (mWindowManager.isRotationFrozen()) { 676 // Calling out with a lock held is fine since if the system 677 // process is gone the client calling in will be killed. 678 mInitialFrozenRotation = mWindowManager.getDefaultDisplayRotation(); 679 } 680 } catch (RemoteException re) { 681 /* ignore */ 682 } 683 } 684 restoreRotationStateLocked()685 private void restoreRotationStateLocked() { 686 try { 687 if (mInitialFrozenRotation != INITIAL_FROZEN_ROTATION_UNSPECIFIED) { 688 // Calling out with a lock held is fine since if the system 689 // process is gone the client calling in will be killed. 690 mWindowManager.freezeRotation(mInitialFrozenRotation, 691 /* caller= */ "UiAutomationConnection#restoreRotationStateLocked"); 692 } else { 693 // Calling out with a lock held is fine since if the system 694 // process is gone the client calling in will be killed. 695 mWindowManager.thawRotation( 696 /* caller= */ "UiAutomationConnection#restoreRotationStateLocked"); 697 } 698 } catch (RemoteException re) { 699 /* ignore */ 700 } 701 } 702 isConnectedLocked()703 private boolean isConnectedLocked() { 704 return mClient != null; 705 } 706 throwIfShutdownLocked()707 private void throwIfShutdownLocked() { 708 if (mIsShutdown) { 709 throw new IllegalStateException("Connection shutdown!"); 710 } 711 } 712 throwIfNotConnectedLocked()713 private void throwIfNotConnectedLocked() { 714 if (!isConnectedLocked()) { 715 throw new IllegalStateException("Not connected!"); 716 } 717 } 718 throwIfCalledByNotTrustedUidLocked()719 private void throwIfCalledByNotTrustedUidLocked() { 720 final int callingUid = Binder.getCallingUid(); 721 if (callingUid != mOwningUid && mOwningUid != Process.SYSTEM_UID 722 && callingUid != 0 /*root*/) { 723 throw new SecurityException("Calling from not trusted UID!"); 724 } 725 } 726 } 727