• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.device.collectors;
17 
18 import android.os.Bundle;
19 import androidx.annotation.VisibleForTesting;
20 import android.util.Log;
21 
22 import org.junit.runner.Description;
23 import org.junit.runner.Result;
24 
25 import java.util.Timer;
26 import java.util.TimerTask;
27 
28 /**
29  * Implementation of {@link BaseMetricListener} that allows to run a periodic collection during the
30  * instrumentation run. Implementing {@link #collect(DataRecord, Description)} as the periodic task
31  * running. It is possible to run some actions before and at the end of the periodic run using
32  * {@link #onStart(DataRecord, Description)} and {@link #onEnd(DataRecord, Result)}.
33  */
34 public abstract class ScheduledRunMetricListener extends BaseMetricListener {
35 
36     public static final String INTERVAL_ARG_KEY = "interval";
37     private static final long DEFAULT_INTERVAL_MS = 60 * 1000l; // 1 min
38 
39     private Timer mTimer;
40 
ScheduledRunMetricListener()41     public ScheduledRunMetricListener() {}
42 
43     @VisibleForTesting
ScheduledRunMetricListener(Bundle argsBundle)44     ScheduledRunMetricListener(Bundle argsBundle) {
45         super(argsBundle);
46     }
47 
48     @Override
onTestRunStart(final DataRecord runData, final Description description)49     public final void onTestRunStart(final DataRecord runData, final Description description) {
50         Log.d(getTag(), "Starting");
51         onStart(runData, description);
52         // TODO: could this be done with Handlers ?
53         mTimer = new Timer();
54         TimerTask timerTask =
55                 new TimerTask() {
56                     @Override
57                     public void run() {
58                         try {
59                             collect(runData, description);
60                         } catch (InterruptedException e) {
61                             mTimer.cancel();
62                             Thread.currentThread().interrupt();
63                             Log.e(getTag(), "Interrupted exception thrown from task:", e);
64                         }
65                     }
66                 };
67 
68         mTimer.scheduleAtFixedRate(timerTask, 0, getIntervalFromArgs());
69     }
70 
71     @Override
onTestRunEnd(DataRecord runData, Result result)72     public final void onTestRunEnd(DataRecord runData, Result result) {
73         if (mTimer != null) {
74             mTimer.cancel();
75             mTimer.purge();
76         }
77         onEnd(runData, result);
78         Log.d(getTag(), "Finished");
79     }
80 
81     /**
82      * Executed when entering this collector.
83      *
84      * @param runData the {@link DataRecord} where to put metrics.
85      * @param description the {@link Description} for the test run.
86      */
onStart(DataRecord runData, Description description)87     void onStart(DataRecord runData, Description description) {
88         // Does nothing.
89     }
90 
91     /**
92      * Executed when finishing this collector.
93      *
94      * @param runData the {@link DataRecord} where to put metrics.
95      * @param result the {@link Result} of the test run about to end.
96      */
onEnd(DataRecord runData, Result result)97     void onEnd(DataRecord runData, Result result) {
98         // Does nothing.
99     }
100 
101     /**
102      * Task periodically & asynchronously run during the test running.
103      *
104      * @param runData the {@link DataRecord} where to put metrics.
105      * @param description the {@link Description} of the run in progress.
106      * @throws InterruptedException
107      */
collect(DataRecord runData, Description description)108     public abstract void collect(DataRecord runData, Description description)
109             throws InterruptedException;
110 
111     /**
112      * Extract the interval from the instrumentation arguments or use the default interval value.
113      */
getIntervalFromArgs()114     private long getIntervalFromArgs() {
115         String intervalValue = getArgsBundle().getString(INTERVAL_ARG_KEY);
116         long interval = 0L;
117         try {
118             interval = Long.parseLong(intervalValue);
119         } catch (NumberFormatException e) {
120             Log.e(getTag(), "Failed to parse the interval value.", e);
121         }
122         // In case invalid or no interval was specified, we use the default one.
123         if (interval <= 0l) {
124             Log.d(getTag(),
125                     String.format(
126                             "Using default interval %s for periodic task. %s could not be used.",
127                             DEFAULT_INTERVAL_MS, interval));
128             interval = DEFAULT_INTERVAL_MS;
129         }
130         return interval;
131     }
132 }
133