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