• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.tradefed.targetprep;
17 
18 import com.android.annotations.VisibleForTesting;
19 import com.android.tradefed.config.Option;
20 import com.android.tradefed.config.OptionClass;
21 import com.android.tradefed.device.DeviceNotAvailableException;
22 import com.android.tradefed.device.ITestDevice;
23 import com.android.tradefed.invoker.TestInformation;
24 import com.android.tradefed.log.LogUtil.CLog;
25 import com.android.tradefed.result.error.InfraErrorIdentifier;
26 import com.android.tradefed.util.IRunUtil;
27 import com.android.tradefed.util.RunUtil;
28 
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 
32 /** An {@link ITargetPreparer} that waits until device's temperature gets down to target */
33 @OptionClass(alias = "temperature-throttle-waiter")
34 public class TemperatureThrottlingWaiter extends BaseTargetPreparer {
35     // temperature raw format example output : Result:30 Raw:7f6f
36     private static final Pattern TEMPERATURE_RAW_FORMAT_REGEX =
37         Pattern.compile("Result:(\\d+)\\sRaw:(\\w+)");
38 
39     // temperature format example output : 30
40     private static final Pattern TEMPERATURE_FORMAT_REGEX = Pattern.compile("\\d+");
41 
42     // temperature format example output:
43     //    Temperature{mValue=28.787504, mType=3, mName=VIRTUAL-SKIN, mStatus=0}
44     private static final Pattern TEMPERATURE_SKIN_FORMAT_PATTERN =
45         Pattern.compile("mValue=([\\d]+.[\\d]+).*mType=3");
46 
47     @Option(name = "poll-interval",
48             description = "Interval in seconds, to poll for device temperature; defaults to 30s")
49     private long mPollIntervalSecs = 30;
50 
51     @Option(name = "max-wait", description = "Max wait time in seconds, for device cool down "
52             + "to target temperature; defaults to 20 minutes")
53     private long mMaxWaitSecs = 60 * 20;
54 
55     @Option(name = "abort-on-timeout", description = "If test should be aborted if device is still "
56         + " above expected temperature; defaults to false")
57     private boolean mAbortOnTimeout = false;
58 
59     @Option(name = "post-idle-wait", description = "Additional time to wait in seconds, after "
60         + "temperature has reached to target; defaults to 120s")
61     private long mPostIdleWaitSecs = 120;
62 
63     public static final String DEVICE_TEMPERATURE_FILE_PATH_NAME = "device-temperature-file-path";
64 
65     @Option(
66             name = DEVICE_TEMPERATURE_FILE_PATH_NAME,
67             description =
68                     "Name of file that contains device"
69                             + "temperature. Example: /sys/class/hwmon/hwmon1/device/msm_therm")
70     private String mDeviceTemperatureFilePath = null;
71 
72     public static final String DEVICE_TEMPERATURE_COMMAND_NAME = "device-temperature-command";
73 
74     @Option(
75         name = DEVICE_TEMPERATURE_COMMAND_NAME,
76         description =
77             "Command for getting device temperature. If both device-temperature-file-path"
78                 + " and device-temperature-command are set,"
79                 + " only device-temperature-file-path will be actived."
80                 + " Example: dumpsys thermalservice"
81                 + " | grep 'mType=3' | grep Temperature | awk 'END{print}'")
82     private String mDeviceTemperatureCommand =
83         "dumpsys thermalservice | grep 'mType=3' | grep Temperature | awk 'END{print}'";
84 
85     @Option(name = "target-temperature", description = "Target Temperature that device should have;"
86         + "defaults to 30c")
87     private int mTargetTemperature = 30;
88 
89     /** {@inheritDoc} */
90     @Override
setUp(TestInformation testInfo)91     public void setUp(TestInformation testInfo)
92             throws TargetSetupError, BuildError, DeviceNotAvailableException {
93         if (mDeviceTemperatureFilePath == null && mDeviceTemperatureCommand == null) {
94             return;
95         }
96         ITestDevice device = testInfo.getDevice();
97         long start = System.currentTimeMillis();
98         long maxWaitMs = mMaxWaitSecs * 1000;
99         long intervalMs = mPollIntervalSecs * 1000;
100         int deviceTemperature = Integer.MAX_VALUE;
101         while (true) {
102             // get device temperature
103             deviceTemperature = getDeviceTemperature(device);
104             if (deviceTemperature > mTargetTemperature) {
105                 CLog.d("Temperature is still high actual %d/expected %d",
106                         deviceTemperature, mTargetTemperature);
107             } else {
108                 CLog.i("Total time elapsed to get to %dc : %ds", mTargetTemperature,
109                         (System.currentTimeMillis() - start) / 1000);
110                 break; // while loop
111             }
112             if ((System.currentTimeMillis() - start) > maxWaitMs) {
113                 CLog.w("Temperature is still high, actual %d/expected %d; waiting after %ds",
114                         deviceTemperature, mTargetTemperature, maxWaitMs);
115                 if (mAbortOnTimeout) {
116                     throw new TargetSetupError(String.format("Temperature is still high after wait "
117                             + "timeout; actual %d/expected %d", deviceTemperature,
118                             mTargetTemperature), device.getDeviceDescriptor());
119                 }
120                 break; // while loop
121             }
122             getRunUtil().sleep(intervalMs);
123         }
124         // extra idle time after reaching the targetl to stable the system
125         getRunUtil().sleep(mPostIdleWaitSecs * 1000);
126         CLog.d("Done waiting, total time elapsed: %ds",
127                 (System.currentTimeMillis() - start) / 1000);
128     }
129 
130     /**
131      * @param device
132      * @throws DeviceNotAvailableException
133      */
getDeviceTemperature(ITestDevice device)134     protected int getDeviceTemperature (ITestDevice device)
135             throws DeviceNotAvailableException, TargetSetupError {
136         String result = executeDeviceTemperatureCommand(device);
137         CLog.i(String.format("Temperature command output : %s", result));
138 
139         if (result == null || result.contains("No such file or directory")) {
140             throw new TargetSetupError(
141                     String.format("File %s doesn't exist", mDeviceTemperatureFilePath),
142                     device.getDeviceDescriptor(),
143                     InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR);
144         }
145         return parseResult(result, device);
146     }
147 
executeDeviceTemperatureCommand(ITestDevice device)148     private String executeDeviceTemperatureCommand(ITestDevice device)
149             throws DeviceNotAvailableException {
150         if (mDeviceTemperatureFilePath != null) {
151             return device.executeShellCommand(
152                 String.format("cat %s", mDeviceTemperatureFilePath)).trim();
153         }
154         if (mDeviceTemperatureCommand != null) {
155             return device.executeShellCommand(mDeviceTemperatureCommand).trim();
156         }
157         return "UNKNOWN";
158     }
159 
parseResult(String result, ITestDevice device)160     private int parseResult(String result, ITestDevice device) throws TargetSetupError {
161         Matcher tempRawFormatMatcher = TEMPERATURE_RAW_FORMAT_REGEX.matcher(result);
162         if (tempRawFormatMatcher.find()) {
163             return Integer.parseInt(tempRawFormatMatcher.group(1));
164         }
165         Matcher tempFormatMatcher = TEMPERATURE_FORMAT_REGEX.matcher(result);
166         if (tempFormatMatcher.find()) {
167             return Integer.parseInt(tempFormatMatcher.group());
168         }
169         Matcher skinFormatMatcher = TEMPERATURE_SKIN_FORMAT_PATTERN.matcher(result);
170         if (skinFormatMatcher.find()) {
171             return Integer.parseInt(skinFormatMatcher.group(1));
172         }
173         throw new TargetSetupError(
174             String.format("result content is not as expected. Content : %s", result),
175                 device.getDeviceDescriptor());
176     }
177 
178     @VisibleForTesting
getRunUtil()179     protected IRunUtil getRunUtil() {
180         return RunUtil.getDefault();
181     }
182 }
183