180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov/* 280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * 480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * you may not use this file except in compliance with the License. 680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * You may obtain a copy of the License at 780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * 880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * 1080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * Unless required by applicable law or agreed to in writing, software 1180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 1280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * See the License for the specific language governing permissions and 1480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * limitations under the License. 1580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov */ 1680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 1780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovpackage android.app; 1880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 1980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.accessibilityservice.AccessibilityServiceInfo; 2080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.accessibilityservice.IAccessibilityServiceClient; 2180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.content.Context; 2280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.graphics.Bitmap; 2380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.hardware.input.InputManager; 2480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.os.Binder; 251376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslavimport android.os.IBinder; 26121e0c073992658ca0ba055f40bf3b130caa819aSvetoslavimport android.os.ParcelFileDescriptor; 2780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.os.Process; 2880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.os.RemoteException; 2980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.os.ServiceManager; 3080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.view.IWindowManager; 3180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.view.InputEvent; 323866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianimport android.view.SurfaceControl; 331376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslavimport android.view.WindowAnimationFrameStats; 341376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslavimport android.view.WindowContentFrameStats; 3580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 3680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovimport android.view.accessibility.IAccessibilityManager; 37121e0c073992658ca0ba055f40bf3b130caa819aSvetoslavimport libcore.io.IoUtils; 38121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav 39121e0c073992658ca0ba055f40bf3b130caa819aSvetoslavimport java.io.FileOutputStream; 40121e0c073992658ca0ba055f40bf3b130caa819aSvetoslavimport java.io.IOException; 41121e0c073992658ca0ba055f40bf3b130caa819aSvetoslavimport java.io.InputStream; 42121e0c073992658ca0ba055f40bf3b130caa819aSvetoslavimport java.io.OutputStream; 4380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 4480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov/** 4580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * This is a remote object that is passed from the shell to an instrumentation 4680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * for enabling access to privileged operations which the shell can do and the 4780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * instrumentation cannot. These privileged operations are needed for implementing 4880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * a {@link UiAutomation} that enables across application testing by simulating 4980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * user actions and performing screen introspection. 5080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * 5180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov * @hide 5280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov */ 5380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganovpublic final class UiAutomationConnection extends IUiAutomationConnection.Stub { 5480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 5580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private static final int INITIAL_FROZEN_ROTATION_UNSPECIFIED = -1; 5680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 5780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface( 5880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov ServiceManager.getService(Service.WINDOW_SERVICE)); 5980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 60121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub 61121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE)); 621376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 6380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private final Object mLock = new Object(); 6480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 653c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav private final Binder mToken = new Binder(); 663c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav 6780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private int mInitialFrozenRotation = INITIAL_FROZEN_ROTATION_UNSPECIFIED; 6880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 6980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private IAccessibilityServiceClient mClient; 7080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 7180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private boolean mIsShutdown; 7280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 7380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private int mOwningUid; 7480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 7580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public void connect(IAccessibilityServiceClient client) { 7680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (client == null) { 7780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalArgumentException("Client cannot be null!"); 7880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 7980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov synchronized (mLock) { 8080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfShutdownLocked(); 8180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (isConnectedLocked()) { 8280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("Already connected."); 8380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 8480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mOwningUid = Binder.getCallingUid(); 8580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov registerUiTestAutomationServiceLocked(client); 8680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov storeRotationStateLocked(); 8780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 8880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 8980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 9080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov @Override 9180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public void disconnect() { 9280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov synchronized (mLock) { 9380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfCalledByNotTrustedUidLocked(); 9480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfShutdownLocked(); 9580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (!isConnectedLocked()) { 9680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("Already disconnected."); 9780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 9880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mOwningUid = -1; 9980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov unregisterUiTestAutomationServiceLocked(); 10080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov restoreRotationStateLocked(); 10180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 10280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 10380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 10480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov @Override 10580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public boolean injectInputEvent(InputEvent event, boolean sync) { 10680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov synchronized (mLock) { 10780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfCalledByNotTrustedUidLocked(); 10880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfShutdownLocked(); 10980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfNotConnectedLocked(); 11080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 11180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov final int mode = (sync) ? InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH 11280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov : InputManager.INJECT_INPUT_EVENT_MODE_ASYNC; 11380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 11480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 11580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov return InputManager.getInstance().injectInputEvent(event, mode); 11680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } finally { 11780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov Binder.restoreCallingIdentity(identity); 11880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 11980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 12080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 12180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov @Override 12280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public boolean setRotation(int rotation) { 12380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov synchronized (mLock) { 12480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfCalledByNotTrustedUidLocked(); 12580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfShutdownLocked(); 12680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfNotConnectedLocked(); 12780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 12880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 12980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 13080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (rotation == UiAutomation.ROTATION_UNFREEZE) { 13180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mWindowManager.thawRotation(); 13280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } else { 13380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mWindowManager.freezeRotation(rotation); 13480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 13580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov return true; 13680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } catch (RemoteException re) { 13780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov /* ignore */ 13880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } finally { 13980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov Binder.restoreCallingIdentity(identity); 14080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 14180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov return false; 14280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 14380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 14480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov @Override 14580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public Bitmap takeScreenshot(int width, int height) { 14680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov synchronized (mLock) { 14780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfCalledByNotTrustedUidLocked(); 14880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfShutdownLocked(); 14980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfNotConnectedLocked(); 15080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 15180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 15280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 1533866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian return SurfaceControl.screenshot(width, height); 15480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } finally { 15580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov Binder.restoreCallingIdentity(identity); 15680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 15780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 15880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 15980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov @Override 1601376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav public boolean clearWindowContentFrameStats(int windowId) throws RemoteException { 1611376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav synchronized (mLock) { 1621376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfCalledByNotTrustedUidLocked(); 1631376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfShutdownLocked(); 1641376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfNotConnectedLocked(); 1651376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1661376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav final long identity = Binder.clearCallingIdentity(); 1671376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav try { 1681376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav IBinder token = mAccessibilityManager.getWindowToken(windowId); 1691376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav if (token == null) { 1701376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return false; 1711376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1721376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return mWindowManager.clearWindowContentFrameStats(token); 1731376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } finally { 1741376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav Binder.restoreCallingIdentity(identity); 1751376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1761376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1771376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 1781376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 1791376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException { 1801376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav synchronized (mLock) { 1811376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfCalledByNotTrustedUidLocked(); 1821376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfShutdownLocked(); 1831376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfNotConnectedLocked(); 1841376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1851376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav final long identity = Binder.clearCallingIdentity(); 1861376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav try { 1871376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav IBinder token = mAccessibilityManager.getWindowToken(windowId); 1881376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav if (token == null) { 1891376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return null; 1901376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1911376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return mWindowManager.getWindowContentFrameStats(token); 1921376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } finally { 1931376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav Binder.restoreCallingIdentity(identity); 1941376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1951376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 1961376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 1971376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 1981376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav public void clearWindowAnimationFrameStats() { 1991376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav synchronized (mLock) { 2001376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfCalledByNotTrustedUidLocked(); 2011376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfShutdownLocked(); 2021376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfNotConnectedLocked(); 2031376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 2041376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav final long identity = Binder.clearCallingIdentity(); 2051376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav try { 2061376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav SurfaceControl.clearAnimationFrameStats(); 2071376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } finally { 2081376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav Binder.restoreCallingIdentity(identity); 2091376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 2101376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 2111376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 2121376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 2131376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav public WindowAnimationFrameStats getWindowAnimationFrameStats() { 2141376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav synchronized (mLock) { 2151376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfCalledByNotTrustedUidLocked(); 2161376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfShutdownLocked(); 2171376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav throwIfNotConnectedLocked(); 2181376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 2191376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav final long identity = Binder.clearCallingIdentity(); 2201376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav try { 2211376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav WindowAnimationFrameStats stats = new WindowAnimationFrameStats(); 2221376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav SurfaceControl.getAnimationFrameStats(stats); 2231376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return stats; 2241376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } finally { 2251376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav Binder.restoreCallingIdentity(identity); 2261376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 2271376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 2281376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 2291376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 230121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav public void executeShellCommand(String command, ParcelFileDescriptor sink) 231121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav throws RemoteException { 232121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav synchronized (mLock) { 233121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav throwIfCalledByNotTrustedUidLocked(); 234121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav throwIfShutdownLocked(); 235121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav throwIfNotConnectedLocked(); 236121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } 237121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav 238121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav InputStream in = null; 239121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav OutputStream out = null; 240121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav 241121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav try { 242121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav java.lang.Process process = Runtime.getRuntime().exec(command); 243121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav 244121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav in = process.getInputStream(); 245121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav out = new FileOutputStream(sink.getFileDescriptor()); 246121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav 247121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav final byte[] buffer = new byte[8192]; 248121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav while (true) { 249121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav final int readByteCount = in.read(buffer); 250121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav if (readByteCount < 0) { 251121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav break; 252121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } 253121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav out.write(buffer, 0, readByteCount); 254121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } 255121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } catch (IOException ioe) { 256121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav throw new RuntimeException("Error running shell command", ioe); 257121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } finally { 258121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav IoUtils.closeQuietly(in); 259121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav IoUtils.closeQuietly(out); 260121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav IoUtils.closeQuietly(sink); 261121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } 262121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav } 263121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav 264121e0c073992658ca0ba055f40bf3b130caa819aSvetoslav @Override 26580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public void shutdown() { 26680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov synchronized (mLock) { 2679663fd09e9dc14a17d3828665ab11a256c4a5c96Svetoslav if (isConnectedLocked()) { 2689663fd09e9dc14a17d3828665ab11a256c4a5c96Svetoslav throwIfCalledByNotTrustedUidLocked(); 2699663fd09e9dc14a17d3828665ab11a256c4a5c96Svetoslav } 27080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throwIfShutdownLocked(); 27180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mIsShutdown = true; 27280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (isConnectedLocked()) { 27380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov disconnect(); 27480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 27580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 27680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 27780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 27880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void registerUiTestAutomationServiceLocked(IAccessibilityServiceClient client) { 27980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface( 28080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)); 28111adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 28280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; 28380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; 28480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 28580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS; 28611adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 28711adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 28811adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY 28911adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS); 29080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 29180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // Calling out with a lock held is fine since if the system 29280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // process is gone the client calling in will be killed. 2933c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav manager.registerUiTestAutomationService(mToken, client, info); 29480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mClient = client; 29580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } catch (RemoteException re) { 29680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("Error while registering UiTestAutomationService.", re); 29780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 29880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 29980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 30080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void unregisterUiTestAutomationServiceLocked() { 30180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface( 30280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)); 30380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 30480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // Calling out with a lock held is fine since if the system 30580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // process is gone the client calling in will be killed. 30680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov manager.unregisterUiTestAutomationService(mClient); 30780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mClient = null; 30880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } catch (RemoteException re) { 30980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("Error while unregistering UiTestAutomationService", 31080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov re); 31180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 31280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 31380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 31480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void storeRotationStateLocked() { 31580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 31680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (mWindowManager.isRotationFrozen()) { 31780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // Calling out with a lock held is fine since if the system 31880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // process is gone the client calling in will be killed. 31980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mInitialFrozenRotation = mWindowManager.getRotation(); 32080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 32180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } catch (RemoteException re) { 32280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov /* ignore */ 32380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 32480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 32580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 32680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void restoreRotationStateLocked() { 32780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov try { 32880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (mInitialFrozenRotation != INITIAL_FROZEN_ROTATION_UNSPECIFIED) { 32980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // Calling out with a lock held is fine since if the system 33080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // process is gone the client calling in will be killed. 33180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mWindowManager.freezeRotation(mInitialFrozenRotation); 33280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } else { 33380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // Calling out with a lock held is fine since if the system 33480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov // process is gone the client calling in will be killed. 33580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov mWindowManager.thawRotation(); 33680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 33780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } catch (RemoteException re) { 33880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov /* ignore */ 33980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 34080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 34180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 34280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private boolean isConnectedLocked() { 34380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov return mClient != null; 34480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 34580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 34680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void throwIfShutdownLocked() { 34780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (mIsShutdown) { 34880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("Connection shutdown!"); 34980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 35080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 35180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 35280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void throwIfNotConnectedLocked() { 35380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (!isConnectedLocked()) { 35480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("Not connected!"); 35580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 35680943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 35780943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 35880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov private void throwIfCalledByNotTrustedUidLocked() { 35980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov final int callingUid = Binder.getCallingUid(); 36080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov if (callingUid != mOwningUid && mOwningUid != Process.SYSTEM_UID 36180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov && callingUid != 0 /*root*/) { 36280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new SecurityException("Calling from not trusted UID!"); 36380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 36480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 36580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov} 366