1f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato/*
2f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * Copyright (C) 2007 The Android Open Source Project
3f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato *
4f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
5f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * you may not use this file except in compliance with the License.
6f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * You may obtain a copy of the License at
7f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato *
8f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
9f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato *
10f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * Unless required by applicable law or agreed to in writing, software
11f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
12f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * See the License for the specific language governing permissions and
14f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * limitations under the License.
15f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato */
16f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
17f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratopackage com.android.commands.am;
18f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
19f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.app.IActivityManager;
20f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.app.IInstrumentationWatcher;
21f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.app.Instrumentation;
22f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.app.UiAutomationConnection;
23f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.content.ComponentName;
24f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.content.pm.IPackageManager;
25f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.content.pm.InstrumentationInfo;
26f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.os.Build;
27f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.os.Bundle;
28f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.os.RemoteException;
29f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.os.ServiceManager;
30f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.os.UserHandle;
31f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.util.AndroidException;
32f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.util.proto.ProtoOutputStream;
33f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport android.view.IWindowManager;
34f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
35f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport java.io.IOException;
36f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport java.util.ArrayList;
37f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratoimport java.util.List;
38f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
39f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
40f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato/**
41f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato * Runs the am instrument command
42f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato */
43f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onoratopublic class Instrument {
44f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private final IActivityManager mAm;
45f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private final IPackageManager mPm;
46f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private final IWindowManager mWm;
47f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
48f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    // Command line arguments
49f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public String profileFile = null;
50f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public boolean wait = false;
51f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public boolean rawMode = false;
52f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public boolean proto = false;
53f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public boolean noWindowAnimation = false;
54f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public String abi = null;
55f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public int userId = UserHandle.USER_CURRENT;
56f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public Bundle args = new Bundle();
57f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    // Required
58f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public String componentNameArg;
59f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
60f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
61f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Construct the instrument command runner.
62f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
63f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public Instrument(IActivityManager am, IPackageManager pm) {
64f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        mAm = am;
65f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        mPm = pm;
66f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
67f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
68f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
69f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
70f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Base class for status reporting.
71f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     *
72f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * All the methods on this interface are called within the synchronized block
73f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * of the InstrumentationWatcher, so calls are in order.  However, that means
74f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * you must be careful not to do blocking operations because you don't know
75f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * exactly the locking dependencies.
76f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
77f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private interface StatusReporter {
78f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        /**
79f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         * Status update for tests.
80f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         */
81f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onInstrumentationStatusLocked(ComponentName name, int resultCode,
82f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                Bundle results);
83f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
84f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        /**
85f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         * The tests finished.
86f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         */
87f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onInstrumentationFinishedLocked(ComponentName name, int resultCode,
88f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                Bundle results);
89f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
90f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        /**
91f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         * @param errorText a description of the error
92f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         * @param commandError True if the error is related to the commandline, as opposed
93f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         *      to a test failing.
94f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         */
95f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onError(String errorText, boolean commandError);
96f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
97f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
98f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
99f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Printer for the 'classic' text based status reporting.
100f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
101f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private class TextStatusReporter implements StatusReporter {
102f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        private boolean mRawMode;
103f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
104f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        /**
105f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         * Human-ish readable output.
106f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         *
107f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         * @param rawMode   In "raw mode" (true), all bundles are dumped.
108f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         *                  In "pretty mode" (false), if a bundle includes
109f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         *                  Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
110f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato         */
111f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public TextStatusReporter(boolean rawMode) {
112f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            mRawMode = rawMode;
113f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
114f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
115f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
116f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onInstrumentationStatusLocked(ComponentName name, int resultCode,
117f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                Bundle results) {
118f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // pretty printer mode?
119f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            String pretty = null;
120f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (!mRawMode && results != null) {
121f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
122f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
123f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (pretty != null) {
124f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.print(pretty);
125f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            } else {
126f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                if (results != null) {
127f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    for (String key : results.keySet()) {
128f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        System.out.println(
129f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                                "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
130f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    }
131f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
132f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
133f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
134f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
135f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
136f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
137f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onInstrumentationFinishedLocked(ComponentName name, int resultCode,
138f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                Bundle results) {
139f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // pretty printer mode?
140f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            String pretty = null;
141f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (!mRawMode && results != null) {
142f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
143f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
144f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (pretty != null) {
145f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.println(pretty);
146f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            } else {
147f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                if (results != null) {
148f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    for (String key : results.keySet()) {
149f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        System.out.println(
150f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                                "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
151f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    }
152f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
153f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.println("INSTRUMENTATION_CODE: " + resultCode);
154f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
155f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
156f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
157f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
158f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onError(String errorText, boolean commandError) {
159f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // The regular BaseCommand error printing will print the commandErrors.
160f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (!commandError) {
161f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.println(errorText);
162f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
163f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
164f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
165f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
166f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
167f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Printer for the protobuf based status reporting.
168f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
169f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private class ProtoStatusReporter implements StatusReporter {
170f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
171f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onInstrumentationStatusLocked(ComponentName name, int resultCode,
172f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                Bundle results) {
173f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final ProtoOutputStream proto = new ProtoOutputStream();
174f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
175f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final long token = proto.startRepeatedObject(InstrumentationData.Session.TEST_STATUS);
176f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
177f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.writeSInt32(InstrumentationData.TestStatus.RESULT_CODE, resultCode);
178f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            writeBundle(proto, InstrumentationData.TestStatus.RESULTS, results);
179f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
180f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.endRepeatedObject(token);
181f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            writeProtoToStdout(proto);
182f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
183f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
184f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
185f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onInstrumentationFinishedLocked(ComponentName name, int resultCode,
186f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                Bundle results) {
187f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final ProtoOutputStream proto = new ProtoOutputStream();
188f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
189f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final long token = proto.startObject(InstrumentationData.Session.SESSION_STATUS);
190f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
191f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.writeEnum(InstrumentationData.SessionStatus.STATUS_CODE,
192f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    InstrumentationData.SESSION_FINISHED);
193f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.writeSInt32(InstrumentationData.SessionStatus.RESULT_CODE, resultCode);
194f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            writeBundle(proto, InstrumentationData.SessionStatus.RESULTS, results);
195f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
196f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.endObject(token);
197f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            writeProtoToStdout(proto);
198f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
199f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
200f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
201f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void onError(String errorText, boolean commandError) {
202f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final ProtoOutputStream proto = new ProtoOutputStream();
203f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
204f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final long token = proto.startObject(InstrumentationData.Session.SESSION_STATUS);
205f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
206f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.writeEnum(InstrumentationData.SessionStatus.STATUS_CODE,
207f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    InstrumentationData.SESSION_ABORTED);
208f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.writeString(InstrumentationData.SessionStatus.ERROR_TEXT, errorText);
209f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
210f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.endObject(token);
211f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            writeProtoToStdout(proto);
212f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
213f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
214f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        private void writeBundle(ProtoOutputStream proto, long fieldId, Bundle bundle) {
215f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final long bundleToken = proto.startObject(fieldId);
216f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
217f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            for (final String key: bundle.keySet()) {
218f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                final long entryToken = proto.startRepeatedObject(
219f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        InstrumentationData.ResultsBundle.ENTRIES);
220f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
221f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                proto.writeString(InstrumentationData.ResultsBundleEntry.KEY, key);
222f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
223f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                final Object val = bundle.get(key);
224f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                if (val instanceof String) {
225f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeString(InstrumentationData.ResultsBundleEntry.VALUE_STRING,
226f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            (String)val);
227f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Byte) {
228f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeSInt32(InstrumentationData.ResultsBundleEntry.VALUE_INT,
229f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            ((Byte)val).intValue());
230f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Double) {
231f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeDouble(InstrumentationData.ResultsBundleEntry.VALUE_DOUBLE,
232f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            ((Double)val).doubleValue());
233f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Float) {
234f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeFloat(InstrumentationData.ResultsBundleEntry.VALUE_FLOAT,
235f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            ((Float)val).floatValue());
236f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Integer) {
237f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeSInt32(InstrumentationData.ResultsBundleEntry.VALUE_INT,
238f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            ((Integer)val).intValue());
239f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Long) {
240f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeSInt64(InstrumentationData.ResultsBundleEntry.VALUE_LONG,
241f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            ((Long)val).longValue());
242f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Short) {
243f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    proto.writeSInt32(InstrumentationData.ResultsBundleEntry.VALUE_INT,
244f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            ((Short)val).intValue());
245f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                } else if (val instanceof Bundle) {
246f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    writeBundle(proto, InstrumentationData.ResultsBundleEntry.VALUE_BUNDLE,
247f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            (Bundle)val);
248f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
249f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
250f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                proto.endRepeatedObject(entryToken);
251f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
252f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
253f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            proto.endObject(bundleToken);
254f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
255f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
256f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        private void writeProtoToStdout(ProtoOutputStream proto) {
257f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            try {
258f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.write(proto.getBytes());
259f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.out.flush();
260f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            } catch (IOException ex) {
261f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                System.err.println("Error writing finished response: ");
262f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                ex.printStackTrace(System.err);
263f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
264f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
265f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
266f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
267f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
268f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
269f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Callbacks from the remote instrumentation instance.
270f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
271f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
272f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        private final StatusReporter mReporter;
273f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
274f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        private boolean mFinished = false;
275f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
276f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public InstrumentationWatcher(StatusReporter reporter) {
277f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            mReporter = reporter;
278f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
279f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
280f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
281f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
282f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            synchronized (this) {
283f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                mReporter.onInstrumentationStatusLocked(name, resultCode, results);
284f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                notifyAll();
285f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
286f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
287f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
288f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        @Override
289f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public void instrumentationFinished(ComponentName name, int resultCode, Bundle results) {
290f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            synchronized (this) {
291f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                mReporter.onInstrumentationFinishedLocked(name, resultCode, results);
292f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                mFinished = true;
293f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                notifyAll();
294f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
295f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
296f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
297f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        public boolean waitForFinish() {
298f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            synchronized (this) {
299f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                while (!mFinished) {
300f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    try {
301f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        if (!mAm.asBinder().pingBinder()) {
302f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            return false;
303f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        }
304f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        wait(1000);
305f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    } catch (InterruptedException e) {
306f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        throw new IllegalStateException(e);
307f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    }
308f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
309f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
310f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            return true;
311f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
312f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
313f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
314f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
315f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Figure out which component they really meant.
316f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
317f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    private ComponentName parseComponentName(String cnArg) throws Exception {
318f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        if (cnArg.contains("/")) {
319f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            ComponentName cn = ComponentName.unflattenFromString(cnArg);
320f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
321f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            return cn;
322f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        } else {
323f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
324f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
325f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final int numInfos = infos == null ? 0: infos.size();
326f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            ArrayList<ComponentName> cns = new ArrayList<>();
327f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            for (int i = 0; i < numInfos; i++) {
328f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                InstrumentationInfo info = infos.get(i);
329f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
330f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                ComponentName c = new ComponentName(info.packageName, info.name);
331f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                if (cnArg.equals(info.packageName)) {
332f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    cns.add(c);
333f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
334f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
335f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
336f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (cns.size() == 0) {
337f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
338f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            } else if (cns.size() == 1) {
339f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                return cns.get(0);
340f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            } else {
341f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                StringBuilder cnsStr = new StringBuilder();
342f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                final int numCns = cns.size();
343f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                for (int i = 0; i < numCns; i++) {
344f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    cnsStr.append(cns.get(i).flattenToString());
345f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    cnsStr.append(", ");
346f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
347f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
348f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                // Remove last ", "
349f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                cnsStr.setLength(cnsStr.length() - 2);
350f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
351f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                throw new IllegalArgumentException("Found multiple instrumentations: "
352f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        + cnsStr.toString());
353f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
354f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
355f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
356f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
357f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    /**
358f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     * Run the instrumentation.
359f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato     */
360f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    public void run() throws Exception {
361f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        StatusReporter reporter = null;
362f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        float[] oldAnims = null;
363f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
364f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        try {
365f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Choose which output we will do.
366f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (proto) {
367f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                reporter = new ProtoStatusReporter();
368f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            } else if (wait) {
369f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                reporter = new TextStatusReporter(rawMode);
370f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
371f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
372f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Choose whether we have to wait for the results.
373f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            InstrumentationWatcher watcher = null;
374f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            UiAutomationConnection connection = null;
375f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (reporter != null) {
376f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                watcher = new InstrumentationWatcher(reporter);
377f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                connection = new UiAutomationConnection();
378f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
379f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
380f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Set the window animation if necessary
381f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (noWindowAnimation) {
382f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                oldAnims = mWm.getAnimationScales();
383f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                mWm.setAnimationScale(0, 0.0f);
384f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                mWm.setAnimationScale(1, 0.0f);
385e5b44043f75bab47955652b5bd98502ce2294f37Chet Haase                mWm.setAnimationScale(2, 0.0f);
386f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
387f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
388f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Figure out which component we are tring to do.
389f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            final ComponentName cn = parseComponentName(componentNameArg);
390f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
391f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Choose an ABI if necessary
392f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (abi != null) {
393f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                final String[] supportedAbis = Build.SUPPORTED_ABIS;
394f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                boolean matched = false;
395f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                for (String supportedAbi : supportedAbis) {
396f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    if (supportedAbi.equals(abi)) {
397f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        matched = true;
398f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        break;
399f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    }
400f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
401f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                if (!matched) {
402f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    throw new AndroidException(
403f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                            "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi);
404f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
405f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
406f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
407f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Start the instrumentation
408f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId,
409f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                        abi)) {
410f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
411f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
412f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
413f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // If we have been requested to wait, do so until the instrumentation is finished.
414f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (watcher != null) {
415f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                if (!watcher.waitForFinish()) {
416f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    reporter.onError("INSTRUMENTATION_ABORTED: System has crashed.", false);
417f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                    return;
418f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                }
419f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
420f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        } catch (Exception ex) {
421f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Report failures
422f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (reporter != null) {
423f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                reporter.onError(ex.getMessage(), true);
424f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
425f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
426f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // And re-throw the exception
427f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            throw ex;
428f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        } finally {
429f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            // Clean up
430f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            if (oldAnims != null) {
431f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato                mWm.setAnimationScales(oldAnims);
432f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato            }
433f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato        }
434f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato    }
435f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato}
436f0c719821dfdd32e37c4de6b4d640cefcda7b32aJoe Onorato
437