15f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka/* 25f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * Copyright (C) 2017 The Android Open Source Project 35f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * 45f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * Licensed under the Apache License, Version 2.0 (the "License"); 55f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * you may not use this file except in compliance with the License. 65f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * You may obtain a copy of the License at 75f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * 85f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * http://www.apache.org/licenses/LICENSE-2.0 95f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * 105f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * Unless required by applicable law or agreed to in writing, software 115f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * distributed under the License is distributed on an "AS IS" BASIS, 125f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * See the License for the specific language governing permissions and 145f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka * limitations under the License. 155f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka */ 165f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shankapackage android.multiuser; 175f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 185f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shankaimport android.os.Bundle; 195f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shankaimport android.os.SystemClock; 203de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolovimport android.support.test.InstrumentationRegistry; 213de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolovimport android.support.test.uiautomator.UiDevice; 225f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 233de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolovimport java.io.IOException; 245f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shankaimport java.util.ArrayList; 255f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 265f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka// Based on //platform/frameworks/base/apct-tests/perftests/utils/BenchmarkState.java 275f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shankapublic class BenchmarkRunner { 285f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 293de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov private static final long COOL_OFF_PERIOD_MS = 1000; 305f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 315f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private static final int NUM_ITERATIONS = 4; 325f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 335f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private static final int NOT_STARTED = 0; // The benchmark has not started yet. 345f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private static final int RUNNING = 1; // The benchmark is running. 355f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private static final int PAUSED = 2; // The benchmark is paused 365f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private static final int FINISHED = 3; // The benchmark has stopped. 375f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 385f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private final BenchmarkResults mResults = new BenchmarkResults(); 395f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private int mState = NOT_STARTED; // Current benchmark state. 405f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private int mIteration; 415f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 425f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public long mStartTimeNs; 435f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public long mPausedDurationNs; 445f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public long mPausedTimeNs; 455f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 465f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public boolean keepRunning() { 475f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka switch (mState) { 485f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka case NOT_STARTED: 495f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mState = RUNNING; 505f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka prepareForNextRun(); 515f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka return true; 525f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka case RUNNING: 535f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mIteration++; 545f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka return startNextTestRun(); 555f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka case PAUSED: 565f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka throw new IllegalStateException("Benchmarking is in paused state"); 575f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka case FINISHED: 585f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka throw new IllegalStateException("Benchmarking is finished"); 595f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka default: 605f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka throw new IllegalStateException("BenchmarkRunner is in unknown state"); 615f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 625f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 635f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 645f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private boolean startNextTestRun() { 655f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mResults.addDuration(System.nanoTime() - mStartTimeNs - mPausedDurationNs); 665f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka if (mIteration == NUM_ITERATIONS) { 675f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mState = FINISHED; 685f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka return false; 695f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } else { 705f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka prepareForNextRun(); 715f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka return true; 725f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 735f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 745f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 755f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka private void prepareForNextRun() { 765f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka SystemClock.sleep(COOL_OFF_PERIOD_MS); 773de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov try { 783de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) 793de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov .executeShellCommand("am wait-for-broadcast-idle"); 803de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov } catch (IOException e) { 813de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov throw new IllegalStateException("Cannot execute shell command", e); 823de2b2e14e3af98cbaf0951ef5c786885d9b9d68Fyodor Kupolov } 835f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mStartTimeNs = System.nanoTime(); 845f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mPausedDurationNs = 0; 855f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 865f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 875f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public void pauseTiming() { 885f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka if (mState != RUNNING) { 895f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka throw new IllegalStateException("Unable to pause the runner: not running currently"); 905f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 915f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mPausedTimeNs = System.nanoTime(); 925f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mState = PAUSED; 935f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 945f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 955f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public void resumeTiming() { 965f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka if (mState != PAUSED) { 975f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka throw new IllegalStateException("Unable to resume the runner: already running"); 985f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 995f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mPausedDurationNs += System.nanoTime() - mPausedTimeNs; 1005f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka mState = RUNNING; 1015f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 1025f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 1032d0278b09f89a13a0ec4be91fdde2e7a682c1197Sudheer Shanka public Bundle getStatsToReport() { 1042d0278b09f89a13a0ec4be91fdde2e7a682c1197Sudheer Shanka return mResults.getStatsToReport(); 1052d0278b09f89a13a0ec4be91fdde2e7a682c1197Sudheer Shanka } 1062d0278b09f89a13a0ec4be91fdde2e7a682c1197Sudheer Shanka 1072d0278b09f89a13a0ec4be91fdde2e7a682c1197Sudheer Shanka public Bundle getStatsToLog() { 1082d0278b09f89a13a0ec4be91fdde2e7a682c1197Sudheer Shanka return mResults.getStatsToLog(); 1095f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 1105f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka 1115f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka public ArrayList<Long> getAllDurations() { 1125f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka return mResults.getAllDurations(); 1135f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka } 1145f76e1fa85f5c189d57860b0b5b02cace139204bSudheer Shanka}