1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.multiuser; 17 18 import android.annotation.Nullable; 19 import android.os.Bundle; 20 import android.os.SystemClock; 21 import android.perftests.utils.ShellHelper; 22 23 import java.util.ArrayList; 24 25 // Based on //platform/frameworks/base/apct-tests/perftests/utils/BenchmarkState.java 26 public class BenchmarkRunner { 27 28 private static final long COOL_OFF_PERIOD_MS = 1000; 29 30 private static final int NUM_ITERATIONS = 4; 31 32 private static final int NOT_STARTED = 0; // The benchmark has not started yet. 33 private static final int RUNNING = 1; // The benchmark is running. 34 private static final int PAUSED = 2; // The benchmark is paused 35 private static final int FINISHED = 3; // The benchmark has stopped. 36 37 private final BenchmarkResults mResults = new BenchmarkResults(); 38 private int mState = NOT_STARTED; // Current benchmark state. 39 private int mIteration = 1; 40 41 public long mStartTimeNs; 42 public long mPausedDurationNs; 43 public long mPausedTimeNs; 44 45 private Throwable mFirstFailure = null; 46 keepRunning()47 public boolean keepRunning() { 48 switch (mState) { 49 case NOT_STARTED: 50 mState = RUNNING; 51 prepareForNextRun(); 52 return true; 53 case RUNNING: 54 mIteration++; 55 return startNextTestRun(); 56 case PAUSED: 57 throw new IllegalStateException("Benchmarking is in paused state"); 58 case FINISHED: 59 throw new IllegalStateException("Benchmarking is finished"); 60 default: 61 throw new IllegalStateException("BenchmarkRunner is in unknown state"); 62 } 63 } 64 startNextTestRun()65 private boolean startNextTestRun() { 66 mResults.addDuration(System.nanoTime() - mStartTimeNs - mPausedDurationNs); 67 if (mIteration == NUM_ITERATIONS + 1) { 68 mState = FINISHED; 69 return false; 70 } else { 71 prepareForNextRun(); 72 return true; 73 } 74 } 75 prepareForNextRun()76 private void prepareForNextRun() { 77 SystemClock.sleep(COOL_OFF_PERIOD_MS); 78 ShellHelper.runShellCommand("am wait-for-broadcast-idle"); 79 mStartTimeNs = System.nanoTime(); 80 mPausedDurationNs = 0; 81 } 82 pauseTiming()83 public void pauseTiming() { 84 if (mState != RUNNING) { 85 throw new IllegalStateException("Unable to pause the runner: not running currently"); 86 } 87 mPausedTimeNs = System.nanoTime(); 88 mState = PAUSED; 89 } 90 resumeTiming()91 public void resumeTiming() { 92 if (mState != PAUSED) { 93 throw new IllegalStateException("Unable to resume the runner: already running"); 94 } 95 mPausedDurationNs += System.nanoTime() - mPausedTimeNs; 96 mState = RUNNING; 97 } 98 getStatsToReport()99 public Bundle getStatsToReport() { 100 return mResults.getStatsToReport(); 101 } 102 getStatsToLog()103 public Bundle getStatsToLog() { 104 return mResults.getStatsToLog(); 105 } 106 getAllDurations()107 public ArrayList<Long> getAllDurations() { 108 return mResults.getAllDurations(); 109 } 110 111 /** Returns which iteration (starting at 1) the Runner is currently on. */ getIteration()112 public int getIteration() { 113 return mIteration; 114 } 115 116 /** 117 * Marks the test run as failed, along with a message of why. 118 * Only the first fail message is retained. 119 */ markAsFailed(Throwable err)120 public void markAsFailed(Throwable err) { 121 if (mFirstFailure == null) { 122 mFirstFailure = err; 123 } 124 } 125 126 /** Gets the failure message if the test failed; otherwise {@code null}. */ getErrorOrNull()127 public @Nullable Throwable getErrorOrNull() { 128 if (mFirstFailure != null) { 129 return mFirstFailure; 130 } 131 if (mState != FINISHED) { 132 return new AssertionError("BenchmarkRunner state is not FINISHED."); 133 } 134 return null; 135 } 136 }