Cts测试框架笔记
// TODO: currently treat all exceptions the same. In future consider different recovery mechanisms for time out's vs IOExceptions
在android 8.1中 处理异常还没考虑 针对性的处理 都是调用recoverDevice() ,等设备在线 设备不在线就会异常
protected boolean performDeviceAction(String actionDescription, final DeviceAction action,
int retryAttempts) throws DeviceNotAvailableException {
for (int i = 0; i < retryAttempts + 1; i++) {
try {
return action.run();
} catch (TimeoutException e) {
logDeviceActionException(actionDescription, e);
} catch (IOException e) {
logDeviceActionException(actionDescription, e);
} catch (InstallException e) {
logDeviceActionException(actionDescription, e);
} catch (SyncException e) {
logDeviceActionException(actionDescription, e);
// a SyncException is not necessarily a device communication problem
// do additional diagnosis
if (!e.getErrorCode().equals(SyncError.BUFFER_OVERRUN) &&
!e.getErrorCode().equals(SyncError.TRANSFER_PROTOCOL_ERROR)) {
// this is a logic problem, doesn't need recovery or to be retried
return false;
}
} catch (AdbCommandRejectedException e) {
logDeviceActionException(actionDescription, e);
} catch (ShellCommandUnresponsiveException e) {
CLog.w("Device %s stopped responding when attempting %s", getSerialNumber(),
actionDescription);
}
// TODO: currently treat all exceptions the same. In future consider different recovery
// mechanisms for time out's vs IOExceptions
recoverDevice();
}
}
@Override
public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline)
throws DeviceNotAvailableException {
...
// wait for device online
IDevice device = monitor.waitForDeviceOnline(mOnlineWaitTime);
if (device == null) {
handleDeviceNotAvailable(monitor, recoverUntilOnline);
// function returning implies that recovery is successful, check battery level here
checkMinBatteryLevel(getDeviceAfterRecovery(monitor));
return;
}
...
}
CTS的启动
相关源码文件
tools//tradefederation/core/src/com/android/tradefed/device/DeviceManager.java // init
tools/tradefederation/core/src/com/android/tradefed/device/ManagedTestDeviceFactory.java // createDevice return IManagedTestDevice; 这里创建不同类型的设备 RemoteAndroidDevice NativeDevice 等等
tools/tradefederation/core/src/com/android/tradefed/device/NativeDevice.java
tools/tradefederation/core/src/com/android/tradefed/device/DeviceStateMonitor.java
tools/tradefederation/core/src/com/android/tradefed/device/NativeDeviceStateMonitor.java // waitForDeviceState 监控设备在线, 提供setState 方法供设置
DeviceManager#init()
- 创建 ManagedTestDeviceFactory
- 创建 ManagedDeviceList
- 调用 startAdbBridgeAndDependentServices() 初始化 adb
protected DeviceMonitorMultiplexer mDvcMon = new DeviceMonitorMultiplexer();
@Override
public void init(IDeviceSelection globalDeviceFilter,
List<IDeviceMonitor> globalDeviceMonitors) {
init(globalDeviceFilter, globalDeviceMonitors,
new ManagedTestDeviceFactory(mFastbootEnabled, DeviceManager.this, mDvcMon));
}
/**
* Initialize the device manager. This must be called once and only once before any other
* methods are called.
*/
public synchronized void init(IDeviceSelection globalDeviceFilter,
List<IDeviceMonitor> globalDeviceMonitors, IManagedTestDeviceFactory deviceFactory) {
// .conf .xml testcase配置文件解析
if (globalDeviceFilter == null) {
globalDeviceFilter = getGlobalConfig().getDeviceRequirements();
}
if (globalDeviceMonitors == null) {
globalDeviceMonitors = getGlobalConfig().getDeviceMonitors();
}
mGlobalHostMonitors = getGlobalConfig().getHostMonitors();
if (mGlobalHostMonitors != null) {
for (IHostMonitor hm : mGlobalHostMonitors) {
hm.start();
}
}
mIsInitialized = true;
mGlobalDeviceFilter = globalDeviceFilter;
if (globalDeviceMonitors != null) {
mDvcMon.addMonitors(globalDeviceMonitors);
}
mManagedDeviceList = new ManagedDeviceList(deviceFactory);
...
// don't start adding devices until fastboot support has been established
startAdbBridgeAndDependentServices();
}
配置读取
- getGlobalConfig()#getHostMonitors()
- getGlobalConfig()#getDeviceRequirements()
- getGlobalConfig()#getDeviceMonitors()
实现类: tools/tradefederation/core/src/com/android/tradefed/config/ConfigurationFactory.java
createConfigurationFromArgs() --> internalCreateConfigurationFromArgs()
||
\/
configDef.createConfiguration() --> new Configuration()
public Configuration(String name, String description) {
mName = name;
mDescription = description;
mConfigMap = new LinkedHashMap<String, List<Object>>();
setDeviceConfig(new DeviceConfigurationHolder(ConfigurationDef.DEFAULT_DEVICE_NAME));
setCommandOptions(new CommandOptions());
setTest(new StubTest());
setLogOutput(new StdoutLogger());
setLogSaver(new FileSystemLogSaver()); // FileSystemLogSaver saves to tmp by default.
setTestInvocationListener(new TextResultReporter());
setMultiTargetPreparer(new StubMultiTargetPreparer());
setSystemStatusCheckers(new ArrayList<ISystemStatusChecker>());
setConfigurationDescriptor(new ConfigurationDescriptor());
setProfiler(new StubTestProfiler());
setDeviceMetricCollectors(new ArrayList<>());
}
startAdbBridgeAndDependentServices()
- 初始化AdbBridge.init()
- AdbBridge设置回调ManagedDeviceListener
- 添加设备addTcpDevices()
AdbBridge.init() 依赖ddmlib,实际是对ddmlib的初始化
/** Initialize adb connection and services depending on adb connection. */
private synchronized void startAdbBridgeAndDependentServices() {
// TODO: Temporarily increase default timeout as workaround for syncFiles timeouts
DdmPreferences.setTimeOut(120 * 1000);
mAdbBridge = createAdbBridge();
mManagedDeviceListener = new ManagedDeviceListener();
// It's important to add the listener before initializing the ADB bridge to avoid a race
// condition when detecting devices.
mAdbBridge.addDeviceChangeListener(mManagedDeviceListener); //设置回调
if (mDvcMon != null) {
mDvcMon.setDeviceLister(new DeviceLister() {
@Override
public List<DeviceDescriptor> listDevices() {
return listAllDevices();
}
});
mDvcMon.run();
}
mAdbBridge.init(false /* client support */, mAdbPath);
addEmulators();
addNullDevices();
addTcpDevices();
List<IMultiDeviceRecovery> recoverers = getGlobalConfig().getMultiDeviceRecoveryHandlers();
if (recoverers != null) {
for (IMultiDeviceRecovery recoverer : recoverers) {
recoverer.setFastbootPath(mFastbootPath);
}
mDeviceRecoverer = new DeviceRecoverer(recoverers);
startDeviceRecoverer();
}
}
ManagedDeviceListener回调处理 ddmlib 负责回调,然后通过ManagedDeviceList.handleDeviceEvent()
更新设备状态
private class ManagedDeviceListener implements IDeviceChangeListener {
@Override
public void deviceChanged(IDevice idevice, int changeMask) {
if ((changeMask & IDevice.CHANGE_STATE) != 0) {
IManagedTestDevice testDevice = mManagedDeviceList.findOrCreate(idevice);
if (testDevice == null) {
return;
}
TestDeviceState newState = TestDeviceState.getStateByDdms(idevice.getState());
CLog.d("Device changed mask " + changeMask + " newState " + newState);
testDevice.setDeviceState(newState);
if (newState == TestDeviceState.ONLINE) {
DeviceEventResponse r = mManagedDeviceList.handleDeviceEvent(testDevice,
DeviceEvent.STATE_CHANGE_ONLINE);
if (r.stateChanged && r.allocationState ==
DeviceAllocationState.Checking_Availability) {
checkAndAddAvailableDevice(testDevice);
}
} else if (DeviceState.OFFLINE.equals(idevice.getState()) ||
DeviceState.UNAUTHORIZED.equals(idevice.getState())) {
// handle device changing to offline or unauthorized.
mManagedDeviceList.handleDeviceEvent(testDevice,
DeviceEvent.STATE_CHANGE_OFFLINE);
}
}
}
...
}
创建设备
第一次肯定是不存设备, 所以会调用 ManagedTestDeviceFactory.createDevice(idevice) 实际返回的是 NativeDevice 对象
addTcpDevices() ---> addAvailableDevice(new TcpDevice("tcp-device-0"))
||
\/
ManagedDeviceList.findOrCreate(TcpDevice idevice) =======> ManagedTestDeviceFactory.createDevice(idevice)
||
\/
new RemoteAndroidDevice(idevice) --> new TestDevice(idevice,new DeviceStateMonitor(), mAllocationMonitor) --> new NativeDevice(idevice,new DeviceStateMonitor(), mAllocationMonitor)
* Add placeholder objects for the max number of tcp devices that can be connected
*/
private static final String TCP_DEVICE_SERIAL_PREFIX = "tcp-device";
private void addTcpDevices() {
for (int i = 0; i < mNumTcpDevicesSupported; i++) {
addAvailableDevice(TcpDevice(String.format("%s-%d", TCP_DEVICE_SERIAL_PREFIX, i)));
}
}
public void addAvailableDevice(IDevice stubDevice) {
IManagedTestDevice d = mManagedDeviceList.findOrCreate(stubDevice);
if (d != null) {
mManagedDeviceList.handleDeviceEvent(d, DeviceEvent.FORCE_AVAILABLE); //设置成FORCE_AVAILABLE
} else {
CLog.e("Could not create stub device");
}
}
ManagedDeviceList.findOrCreate(IDevice idevice)
A thread-safe data structure that holds all devices known to
如果没有这设备就会调用上面的 ManagedTestDeviceFactory#createDevice(IDevice idevice) ,第一次这里肯定没有
// A thread-safe data structure that holds all devices known to {@link DeviceManager}.
public IManagedTestDevice findOrCreate(IDevice idevice) {
if (!isValidDeviceSerial(idevice.getSerialNumber())) {
return null;
}
mListLock.lock();
try {
IManagedTestDevice d = find(idevice.getSerialNumber());
if (d == null || DeviceAllocationState.Unavailable.equals(d.getAllocationState())) {
mList.remove(d);
d = mDeviceFactory.createDevice(idevice);
mList.add(d);
}
return d;
} finally {
mListLock.unlock();
}
}
ManagedTestDeviceFactory#createDevice(IDevice idevice)
创建不同类型的设备 RemoteAndroidDevice NativeDevice 等等
@Override
public IManagedTestDevice createDevice(IDevice idevice) {
IManagedTestDevice testDevice = null;
if (idevice instanceof TcpDevice || isTcpDeviceSerial(idevice.getSerialNumber())) {
// Special device for Tcp device for custom handling.
// 后面的流程是 new RemoteAndroidDevice() --> new TestDevice() --> new NativeDevice()
testDevice = new RemoteAndroidDevice(idevice,
new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled),
mAllocationMonitor);
testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE);
} else if (!checkFrameworkSupport(idevice)) {
// Brillo device instance tier 1 (no framework support)
testDevice = new NativeDevice(idevice,
new NativeDeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled),
mAllocationMonitor);
} else {
// Default to-go device is Android full stack device.
testDevice = new TestDevice(idevice,
new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled),
mAllocationMonitor);
}
....
return testDevice;
}
handleAllocationEvent流程
DeviceManager.checkAndAddAvailableDevice() --> ManagedDeviceList.handleDeviceEvent() --> NativeDevice.handleAllocationEvent() --> DeviceAllocationEventHandler.handleDeviceEvent()
public DeviceEventResponse handleAllocationEvent(DeviceEvent event) {
// keep track of whether state has actually changed or not
boolean stateChanged = false;
DeviceAllocationState newState;
DeviceAllocationState oldState = mAllocationState;
mAllocationStateLock.lock();
try {
// update oldState here, just in case in changed before we got lock
oldState = mAllocationState;
newState = mAllocationState.handleDeviceEvent(event);
if (oldState != newState) {
// state has changed! record this fact, and store the new state
stateChanged = true;
mAllocationState = newState;
}
} finally {
mAllocationStateLock.unlock();
}
if (stateChanged && mAllocationMonitor != null) {
// state has changed! Lets inform the allocation monitor listener
mAllocationMonitor.notifyDeviceStateChange(getSerialNumber(), oldState, newState);
}
return new DeviceEventResponse(newState, stateChanged);
}
mAllocationMonitor.notifyDeviceStateChange()流程
// tools/tradefederation/core/src/com/android/tradefed/command/CommandScheduler.java
IDeviceManager manager = getDeviceManager();
manager.addDeviceMonitor(new AvailDeviceMonitor());
// AvailDeviceMonitor.notifyDeviceStateChange()
@Override
public void notifyDeviceStateChange(String serial, DeviceAllocationState oldState,
DeviceAllocationState newState) {
if (newState.equals(DeviceAllocationState.Available)) {
// new avail device was added, wake up scheduler
mCommandProcessWait.signalEventReceived();
}
}
// Available才唤醒
public synchronized void signalEventReceived() {
mEventReceived = true;
notifyAll();
}