1 /* 2 * Copyright (C) 2018 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 com.android.game.qualification.metric; 17 18 import com.android.tradefed.config.Option; 19 import com.android.tradefed.device.metric.DeviceMetricData; 20 import com.android.tradefed.log.LogUtil.CLog; 21 import com.android.tradefed.metrics.proto.MetricMeasurement; 22 23 import java.util.Map; 24 import java.util.Timer; 25 import java.util.TimerTask; 26 27 /** 28 * Similar to {@link com.android.tradefed.device.metric.ScheduledDeviceMetricCollector} but 29 * customized to use {@link BaseGameQualificationMetricCollector}. 30 */ 31 public abstract class GameQualificationScheduledMetricCollector 32 extends BaseGameQualificationMetricCollector { 33 @Option( 34 name = "fixed-schedule-rate", 35 description = "Schedule the timetask as a fixed schedule rate" 36 ) 37 protected boolean mFixedScheduleRate = false; 38 39 @Option( 40 name = "interval", 41 description = "the interval between two tasks being scheduled", 42 isTimeVal = true 43 ) 44 protected long mIntervalMs = 60 * 1000L; 45 46 private Timer mTimer; 47 48 @Override onStart(DeviceMetricData runData)49 protected final void onStart(DeviceMetricData runData) { 50 if (!isEnabled()) { 51 // Metric collector is only enabled by GameQualificationHostsideController. 52 return; 53 } 54 CLog.d("starting with interval = %s", mIntervalMs); 55 56 synchronized (this) { 57 doStart(runData); 58 } 59 60 mTimer = new Timer(); 61 TimerTask timerTask = 62 new TimerTask() { 63 @Override 64 public void run() { 65 synchronized (GameQualificationScheduledMetricCollector.this) { 66 try { 67 collect(); 68 } catch (Exception e) { 69 mTimer.cancel(); 70 Thread.currentThread().interrupt(); 71 CLog.e("Test app '%s' terminated before data collection was completed.", 72 getApkInfo().getName()); 73 setHasError(true); 74 setErrorMessage(e.getMessage()); 75 } 76 } 77 } 78 }; 79 80 if (mFixedScheduleRate) { 81 mTimer.scheduleAtFixedRate(timerTask, 0, mIntervalMs); 82 } else { 83 mTimer.schedule(timerTask, 0, mIntervalMs); 84 } 85 } 86 87 @Override onEnd( DeviceMetricData runData, Map<String, MetricMeasurement.Metric> currentRunMetrics)88 public final void onEnd( 89 DeviceMetricData runData, 90 Map<String, MetricMeasurement.Metric> currentRunMetrics) { 91 if (!isEnabled()) { 92 return; 93 } 94 95 if (mTimer != null) { 96 mTimer.cancel(); 97 mTimer.purge(); 98 } 99 synchronized (this) { 100 doEnd(runData); 101 } 102 CLog.d("finished"); 103 } 104 105 /** 106 * Task periodically & asynchronously run during the test. 107 */ collect()108 protected abstract void collect(); 109 110 /** 111 * Executed when entering this collector. 112 * 113 * @param runData the {@link DeviceMetricData} where to put metrics. 114 */ doStart(DeviceMetricData runData)115 protected void doStart(DeviceMetricData runData) { 116 // Does nothing. 117 } 118 119 /** 120 * Executed when finishing this collector. 121 * 122 * @param runData the {@link DeviceMetricData} where to put metrics. 123 */ doEnd(DeviceMetricData runData)124 protected void doEnd(DeviceMetricData runData) { 125 // Does nothing. 126 } 127 } 128