1b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes/*
2b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * Copyright (C) 2016 The Android Open Source Project
3b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *
4b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * Licensed under the Apache License, Version 2.0 (the "License");
5b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * you may not use this file except in compliance with the License.
6b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * You may obtain a copy of the License at
7b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *
8b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *        http://www.apache.org/licenses/LICENSE-2.0
9b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * Unless required by applicable law or agreed to in writing, software
10b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * distributed under the License is distributed on an "AS IS" BASIS,
11b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * See the License for the specific language governing permissions and limitations under the
13b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * License.
14b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *
15b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes */
16b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
17b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandespackage com.android.benchmark.ui.automation;
18b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
19b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.annotation.TargetApi;
20b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.app.Instrumentation;
21b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.os.Handler;
22b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.os.HandlerThread;
23b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.os.Looper;
24b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.os.Message;
25b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.view.FrameMetrics;
26b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.view.MotionEvent;
27b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.view.ViewTreeObserver;
28b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.view.Window;
29b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
30b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.results.GlobalResultsStore;
31b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.results.UiBenchmarkResult;
32b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
33b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.util.LinkedList;
34b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.util.List;
35b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.util.concurrent.atomic.AtomicInteger;
36b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
37b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes@TargetApi(24)
38b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandespublic class Automator extends HandlerThread
39b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        implements ViewTreeObserver.OnGlobalLayoutListener, CollectorThread.CollectorListener {
40b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public static final long FRAME_PERIOD_MILLIS = 16;
41b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
42b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private static final int PRE_READY_STATE_COUNT = 3;
43b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private static final String TAG = "Benchmark.Automator";
44b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private final AtomicInteger mReadyState;
45b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
46b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private AutomateCallback mCallback;
47b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private Window mWindow;
48b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private AutomatorHandler mHandler;
49b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private CollectorThread mCollectorThread;
50b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private int mRunId;
51b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private int mIteration;
52b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private String mTestName;
53b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
54b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public static class AutomateCallback {
55b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public void onAutomate() {}
56b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public void onPostInteraction(List<FrameMetrics> metrics) {}
57b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public void onPostAutomate() {}
58b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
59b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        protected final void addInteraction(Interaction interaction) {
60b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (mInteractions == null) {
61b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                return;
62b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
63b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
64b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mInteractions.add(interaction);
65b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
66b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
67b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        protected final void setInteractions(List<Interaction> interactions) {
68b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mInteractions = interactions;
69b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
70b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
71b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private List<Interaction> mInteractions;
72b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
73b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
74b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private static final class AutomatorHandler extends Handler {
75b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public static final int MSG_NEXT_INTERACTION = 0;
76b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public static final int MSG_ON_AUTOMATE = 1;
77b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public static final int MSG_ON_POST_INTERACTION = 2;
78b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private final String mTestName;
79b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private final int mRunId;
80b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private final int mIteration;
81b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
82b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private Instrumentation mInstrumentation;
83b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private volatile boolean mCancelled;
84b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private CollectorThread mCollectorThread;
85b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private AutomateCallback mCallback;
86b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private Window mWindow;
87b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
88b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        LinkedList<Interaction> mInteractions;
89b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private UiBenchmarkResult mResults;
90b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
91b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        AutomatorHandler(Looper looper, Window window, CollectorThread collectorThread,
92b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                         AutomateCallback callback, String testName, int runId, int iteration) {
93b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            super(looper);
94b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
95b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mInstrumentation = new Instrumentation();
96b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
97b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mCallback = callback;
98b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mWindow = window;
99b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mCollectorThread = collectorThread;
100b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mInteractions = new LinkedList<>();
101b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mTestName = testName;
102b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mRunId = runId;
103b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mIteration = iteration;
104b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
105b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
106b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        @Override
107b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public void handleMessage(Message msg) {
108b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (mCancelled) {
109b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                return;
110b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
111b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
112b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            switch (msg.what) {
113b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                case MSG_NEXT_INTERACTION:
114b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    if (!nextInteraction()) {
115b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        stopCollector();
116b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        writeResults();
117b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        mCallback.onPostAutomate();
118b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    }
119b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    break;
120b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                case MSG_ON_AUTOMATE:
121b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    mCollectorThread.attachToWindow(mWindow);
122b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    mCallback.setInteractions(mInteractions);
123b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    mCallback.onAutomate();
124b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    postNextInteraction();
125b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    break;
126b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                case MSG_ON_POST_INTERACTION:
127b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    List<FrameMetrics> collectedStats = (List<FrameMetrics>)msg.obj;
128b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    persistResults(collectedStats);
129b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    mCallback.onPostInteraction(collectedStats);
130b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    postNextInteraction();
131b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    break;
132b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
133b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
134b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
135b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        public void cancel() {
136b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mCancelled = true;
137b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            stopCollector();
138b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
139b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
140b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private void stopCollector() {
141b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mCollectorThread.quitCollector();
142b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
143b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
144b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private boolean nextInteraction() {
145b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
146b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            Interaction interaction = mInteractions.poll();
147b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (interaction != null) {
148b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                doInteraction(interaction);
149b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                return true;
150b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
151b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            return false;
152b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
153b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
154b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private void doInteraction(Interaction interaction) {
155b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (mCancelled) {
156b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                return;
157b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
158b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
159b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mCollectorThread.markInteractionStart();
160b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
161b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (interaction.getType() == Interaction.Type.KEY_EVENT) {
162b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                for (int code : interaction.getKeyCodes()) {
163b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    if (!mCancelled) {
164b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        mInstrumentation.sendKeyDownUpSync(code);
165b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    } else {
166b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        break;
167b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    }
168b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                }
169b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            } else {
170b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                for (MotionEvent event : interaction.getEvents()) {
171b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    if (!mCancelled) {
172b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        mInstrumentation.sendPointerSync(event);
173b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    } else {
174b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        break;
175b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    }
176b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                }
177b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
178b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
179b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
180b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        protected void postNextInteraction() {
181b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            final Message msg = obtainMessage(AutomatorHandler.MSG_NEXT_INTERACTION);
182b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            sendMessage(msg);
183b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
184b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
185b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private void persistResults(List<FrameMetrics> stats) {
186b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (stats.isEmpty()) {
187b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                return;
188b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
189b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
190b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (mResults == null) {
191b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                mResults = new UiBenchmarkResult(stats);
192b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            } else {
193b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                mResults.update(stats);
194b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
195b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
196b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
197b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        private void writeResults() {
198b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            GlobalResultsStore.getInstance(mWindow.getContext())
199b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    .storeRunResults(mTestName, mRunId, mIteration, mResults);
200b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
201b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
202b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
203b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private void initHandler() {
204b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mHandler = new AutomatorHandler(getLooper(), mWindow, mCollectorThread, mCallback,
205b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                mTestName, mRunId, mIteration);
206b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mWindow = null;
207b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mCallback = null;
208b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mCollectorThread = null;
209b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mTestName = null;
210b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mRunId = 0;
211b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mIteration = 0;
212b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
213b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
214b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    @Override
215b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public final void onGlobalLayout() {
216b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        if (!mCollectorThread.isAlive()) {
217b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mCollectorThread.start();
218b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mWindow.getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
219b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            mReadyState.decrementAndGet();
220b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
221b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
222b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
223b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    @Override
224b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public void onCollectorThreadReady() {
225b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        if (mReadyState.decrementAndGet() == 0) {
226b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            initHandler();
227b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            postOnAutomate();
228b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
229b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
230b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
231b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    @Override
232b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    protected void onLooperPrepared() {
233b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        if (mReadyState.decrementAndGet() == 0) {
234b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            initHandler();
235b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            postOnAutomate();
236b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
237b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
238b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
239b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    @Override
240b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public void onPostInteraction(List<FrameMetrics> stats) {
241b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        Message m = mHandler.obtainMessage(AutomatorHandler.MSG_ON_POST_INTERACTION, stats);
242b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mHandler.sendMessage(m);
243b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
244b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
245b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    protected void postOnAutomate() {
246b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        final Message msg = mHandler.obtainMessage(AutomatorHandler.MSG_ON_AUTOMATE);
247b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mHandler.sendMessage(msg);
248b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
249b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
250b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public void cancel() {
251b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mHandler.removeMessages(AutomatorHandler.MSG_NEXT_INTERACTION);
252b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mHandler.cancel();
253b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mHandler = null;
254b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
255b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
256b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public Automator(String testName, int runId, int iteration,
257b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                     Window window, AutomateCallback callback) {
258b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        super("AutomatorThread");
259b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
260b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mTestName = testName;
261b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mRunId = runId;
262b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mIteration = iteration;
263b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mCallback = callback;
264b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mWindow = window;
265b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mWindow.getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(this);
266b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mCollectorThread = new CollectorThread(this);
267b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mReadyState = new AtomicInteger(PRE_READY_STATE_COUNT);
268b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
269b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes}
270