blob: d14747662db098066f7a3020fa1c0d03df2b67ca [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tradefed.targetprep;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunUtil;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* An {@link ITargetPreparer} that checks for a minimum battery charge, and waits for the battery
* to reach a second charging threshold if the minimum charge isn't present.
*/
@OptionClass(alias = "battery-checker")
public class DeviceBatteryLevelChecker implements ITargetPreparer {
@Option(name="min-level", description="Charge level below which we force the device to sit " +
"and charge. Range: 0-100.")
private int mMinChargeLevel = 10;
@Option(name="resume-level", description="Charge level at which we release the device to " +
"begin testing again. Range: 0-100.")
private int mResumeLevel = 80;
@Option(name="poll-time", description="Time in minutes to wait between battery level polls. " +
"Decimal times accepted.")
private double mChargingPollTime = 5.0;
private static final Pattern BATTERY_LEVEL = Pattern.compile("\\s*level: (\\d+)");
private Integer checkBatteryLevel(ITestDevice device) throws DeviceNotAvailableException {
// FIXME: scale the battery level by "scale" instead of assuming 100
String dumpsys = device.executeShellCommand("dumpsys battery");
if (dumpsys != null) {
String[] lines = dumpsys.split("\r?\n");
for (String line : lines) {
Matcher m = BATTERY_LEVEL.matcher(line);
if (m.matches()) {
try {
return Integer.parseInt(m.group(1));
} catch (NumberFormatException e) {
CLog.w("Failed to parse %s as an integer", m.group(1));
}
}
}
}
CLog.w("Failed to determine battery level for device %s. `dumpsys battery` was: %s",
device.getSerialNumber(), dumpsys);
return null;
}
/**
* {@inheritDoc}
*/
public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError, BuildError,
DeviceNotAvailableException {
Integer batteryLevel = checkBatteryLevel(device);
if (batteryLevel == null) {
// we already logged a warning
return;
} else if (batteryLevel < mMinChargeLevel) {
// Time-out. Send the device to the corner
CLog.w("Battery level %d is below the min level %d; holding for device %s to charge " +
"to level %d", batteryLevel, mMinChargeLevel, device.getSerialNumber(),
mResumeLevel);
} else {
// Good to go
CLog.d("Battery level %d is above the minimum of %d; %s is good to go.", batteryLevel,
mMinChargeLevel, device.getSerialNumber());
return;
}
// If we're down here, it's time to hold the device until it reaches mResumeLevel
while (batteryLevel != null && batteryLevel < mResumeLevel) {
// FIXME show periodic status messages with "w" log level
getRunUtil().sleep((long) (mChargingPollTime * 60 * 1000));
Integer newLevel = checkBatteryLevel(device);
if (newLevel == null) {
// weird
CLog.w("Breaking out of wait loop because battery level read failed for device %s",
device.getSerialNumber());
break;
} else if (newLevel < batteryLevel) {
// also weird
CLog.w("Warning: battery discharged from %d to %d on device %s during the last " +
"%d minutes.", batteryLevel, newLevel, device.getSerialNumber(),
mChargingPollTime);
} else {
CLog.d("Battery level for device %s is now %d", device.getSerialNumber(), newLevel);
}
batteryLevel = newLevel;
}
CLog.w("Device %s is now charged to battery level %d; releasing.", device.getSerialNumber(),
batteryLevel);
}
/**
* Get a RunUtil instance
* <p />
* Exposed for unit testing
*/
IRunUtil getRunUtil() {
return RunUtil.getDefault();
}
}