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