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.tradefed.config.Option; 19 import com.android.tradefed.config.OptionClass; 20 import com.android.tradefed.device.DeviceNotAvailableException; 21 import com.android.tradefed.device.ITestDevice; 22 import com.android.tradefed.invoker.TestInformation; 23 import com.android.tradefed.log.LogUtil.CLog; 24 import com.android.tradefed.util.RunUtil; 25 26 import java.util.regex.Matcher; 27 import java.util.regex.Pattern; 28 29 /** An {@link ITargetPreparer} that waits until device's temperature gets down to target */ 30 @OptionClass(alias = "temperature-throttle-waiter") 31 public class TemperatureThrottlingWaiter extends BaseTargetPreparer { 32 33 @Option(name = "poll-interval", 34 description = "Interval in seconds, to poll for device temperature; defaults to 30s") 35 private long mPollIntervalSecs = 30; 36 37 @Option(name = "max-wait", description = "Max wait time in seconds, for device cool down " 38 + "to target temperature; defaults to 20 minutes") 39 private long mMaxWaitSecs = 60 * 20; 40 41 @Option(name = "abort-on-timeout", description = "If test should be aborted if device is still " 42 + " above expected temperature; defaults to false") 43 private boolean mAbortOnTimeout = false; 44 45 @Option(name = "post-idle-wait", description = "Additional time to wait in seconds, after " 46 + "temperature has reached to target; defaults to 120s") 47 private long mPostIdleWaitSecs = 120; 48 49 public static final String DEVICE_TEMPERATURE_FILE_PATH_NAME = "device-temperature-file-path"; 50 51 @Option( 52 name = DEVICE_TEMPERATURE_FILE_PATH_NAME, 53 description = 54 "Name of file that contains device" 55 + "temperature. Example: /sys/class/hwmon/hwmon1/device/msm_therm") 56 private String mDeviceTemperatureFilePath = null; 57 58 @Option(name = "target-temperature", description = "Target Temperature that device should have;" 59 + "defaults to 30c") 60 private int mTargetTemperature = 30; 61 62 /** {@inheritDoc} */ 63 @Override setUp(TestInformation testInfo)64 public void setUp(TestInformation testInfo) 65 throws TargetSetupError, BuildError, DeviceNotAvailableException { 66 if (mDeviceTemperatureFilePath == null) { 67 return; 68 } 69 ITestDevice device = testInfo.getDevice(); 70 long start = System.currentTimeMillis(); 71 long maxWaitMs = mMaxWaitSecs * 1000; 72 long intervalMs = mPollIntervalSecs * 1000; 73 int deviceTemperature = Integer.MAX_VALUE; 74 while (true) { 75 // get device temperature 76 deviceTemperature = getDeviceTemperature(device, mDeviceTemperatureFilePath); 77 if (deviceTemperature > mTargetTemperature) { 78 CLog.d("Temperature is still high actual %d/expected %d", 79 deviceTemperature, mTargetTemperature); 80 } else { 81 CLog.i("Total time elapsed to get to %dc : %ds", mTargetTemperature, 82 (System.currentTimeMillis() - start) / 1000); 83 break; // while loop 84 } 85 if ((System.currentTimeMillis() - start) > maxWaitMs) { 86 CLog.w("Temperature is still high, actual %d/expected %d; waiting after %ds", 87 deviceTemperature, mTargetTemperature, maxWaitMs); 88 if (mAbortOnTimeout) { 89 throw new TargetSetupError(String.format("Temperature is still high after wait " 90 + "timeout; actual %d/expected %d", deviceTemperature, 91 mTargetTemperature), device.getDeviceDescriptor()); 92 } 93 break; // while loop 94 } 95 RunUtil.getDefault().sleep(intervalMs); 96 } 97 // extra idle time after reaching the targetl to stable the system 98 RunUtil.getDefault().sleep(mPostIdleWaitSecs * 1000); 99 CLog.d("Done waiting, total time elapsed: %ds", 100 (System.currentTimeMillis() - start) / 1000); 101 } 102 103 /** 104 * @param device 105 * @param fileName : filename where device temperature is stored 106 * @throws DeviceNotAvailableException 107 */ getDeviceTemperature(ITestDevice device, String fileName)108 protected int getDeviceTemperature (ITestDevice device, String fileName) 109 throws DeviceNotAvailableException, TargetSetupError { 110 int deviceTemp = Integer.MAX_VALUE; 111 String result = device.executeShellCommand( 112 String.format("cat %s", fileName)).trim(); 113 CLog.i(String.format("Temperature file output : %s", result)); 114 115 if (result == null || result.contains("No such file or directory")) { 116 throw new TargetSetupError(String.format("File %s doesn't exist", fileName), 117 device.getDeviceDescriptor()); 118 } 119 120 // temperature raw format example output : Result:30 Raw:7f6f 121 final Pattern TEMPERATURE_RAW_FORMAT_REGEX = Pattern.compile("Result:(\\d+)\\sRaw:(\\w+)"); 122 // temperature format example output : 30 123 final Pattern TEMPERATURE_FORMAT_REGEX = Pattern.compile("\\d+"); 124 Matcher matcher = TEMPERATURE_RAW_FORMAT_REGEX.matcher(result); 125 if (matcher.find()) { 126 deviceTemp = Integer.parseInt(matcher.group(1)); 127 } else { 128 matcher = TEMPERATURE_FORMAT_REGEX.matcher(result); 129 if (matcher.find()) { 130 deviceTemp = Integer.parseInt(matcher.group()); 131 } else { 132 throw new TargetSetupError( 133 String.format("file content is not as expected. Content : %s", result), 134 device.getDeviceDescriptor()); 135 } 136 } 137 138 return deviceTemp; 139 } 140 } 141