# 解析配置文件
Cts框架分為9大部分:
cmd_options:命令行接受的參數選項,command包中。
device_requirements:設備相關要求,device包中
device_options:設備參數要求,device包中
builde_provider:版本提供者,build包中
target_preparer:預置條件準備,targetprep包中
test:測試類型,存在testtype包中
device_recovery:任務執行過程中設備異常后的設備恢復,device包中
logger:日志系統,log包中
result_reporter:結果統計報告,result包中
每一種任務都要配置好這9個組件,如果不配置,框架就采用自己的默認配置,但也是相當于配置了這幾項,所以cts框架的核心在Configuration中。
~~~
private static synchronized Map<String, ObjTypeInfo> getObjTypeMap() {
if (sObjTypeMap == null) {
sObjTypeMap = new HashMap<String, ObjTypeInfo>();
sObjTypeMap.put(BUILD_PROVIDER_TYPE_NAME, new ObjTypeInfo(IBuildProvider.class, false));
sObjTypeMap.put(TARGET_PREPARER_TYPE_NAME, new ObjTypeInfo(ITargetPreparer.class, true));
sObjTypeMap.put(TEST_TYPE_NAME, new ObjTypeInfo(IRemoteTest.class, true));
sObjTypeMap.put(DEVICE_RECOVERY_TYPE_NAME, new ObjTypeInfo(IDeviceRecovery.class, false));
sObjTypeMap.put(LOGGER_TYPE_NAME, new ObjTypeInfo(ILeveledLogOutput.class, false));
sObjTypeMap.put(RESULT_REPORTER_TYPE_NAME, new ObjTypeInfo(ITestInvocationListener.class,
true));
sObjTypeMap.put(CMD_OPTIONS_TYPE_NAME, new ObjTypeInfo(ICommandOptions.class,
false));
sObjTypeMap.put(DEVICE_REQUIREMENTS_TYPE_NAME, new ObjTypeInfo(IDeviceSelection.class,
false));
sObjTypeMap.put(DEVICE_OPTIONS_TYPE_NAME, new ObjTypeInfo(TestDeviceOptions.class,
false));
}
return sObjTypeMap;
}
/**
* Creates an {@link Configuration} with default config objects.
*/
public Configuration(String name, String description) {
mName = name;
mDescription = description;
mConfigMap = new LinkedHashMap<String, List<Object>>();
setCommandOptions(new CommandOptions());
setDeviceRequirements(new DeviceSelectionOptions());
setDeviceOptions(new TestDeviceOptions());
setBuildProvider(new StubBuildProvider());
setTargetPreparer(new StubTargetPreparer());
setTest(new StubTest());
setDeviceRecovery(new WaitDeviceRecovery());
setLogOutput(new StdoutLogger());
setTestInvocationListener(new TextResultReporter());
}
~~~
在getObjTypeMap()可以看出來cts框架為這9個組件定義的接口,只要你的類實現了這個接口,cts就可以通過反射機制找到你的類。Configuration類的構造方法中設置了這幾個接口默認的實現類,如果你沒有配置其他的替代類,cts會默認去加載這些實現類。這些類都是實現了上面方法中對應關系的接口,才能被設置成配置項的。

所有關于類的配置,cts只認你在Configuration類接口的實現類,你如果寫了一個類沒有繼承9大類中的一個接口,你添加了,也會報錯的。從上圖可以看出,cts默認配置了上面幾項,沒有配置的采用默認的。這個講完了,我們就從文章開頭的代碼開始將它是如何一步一步完成這些配置的。
# Debug
以[上一篇文章](http://blog.csdn.net/itfootball/article/details/40210811)中的解析配置文件代碼開始:
~~~
IConfiguration config = getConfigFactory().createConfigurationFromArgs(args);
~~~

調用的是ConfigurationFactory.createConfigurationFromArgs方法:
~~~
/**
* {@inheritDoc}
*/
@Override
public IConfiguration createConfigurationFromArgs(String[] arrayArgs)
throws ConfigurationException {
List<String> listArgs = new ArrayList<String>(arrayArgs.length);
IConfiguration config = internalCreateConfigurationFromArgs(arrayArgs, listArgs);
config.setOptionsFromCommandLineArgs(listArgs);
return config;
}
~~~
該方法又調用了internalCreateConfigurationFromArgs方法,傳入的是參數run cts --plan Signature字符串數組和一個空字符串。
~~~
private IConfiguration internalCreateConfigurationFromArgs(String[] arrayArgs,
List<String> optionArgsRef) throws ConfigurationException {
if (arrayArgs.length == 0) {
throw new ConfigurationException("Configuration to run was not specified");
}
optionArgsRef.addAll(Arrays.asList(arrayArgs));
// first arg is config name
final String configName = optionArgsRef.remove(0);
ConfigurationDef configDef = getConfigurationDef(configName, false);
return configDef.createConfiguration();
}
~~~
該方法中取出第一個參數cts然后傳入getConfigurationDef方法中,獲取ConfigurationDef對象。首先看看ConfigurationDef對象是什么?很簡單,一個ConfigurationDef代表一個配置文件。

~~~
public class ConfigurationDef {
/** a map of object type names to config object class name(s). */
private final Map<String, List<String>> mObjectClassMap;
/** a list of option name/value pairs. */
private final List<OptionDef> mOptionList;
/** a cache of the frequency of every classname */
private final Map<String, Integer> mClassFrequency;
static class OptionDef {
final String name;
final String key;
final String value;
OptionDef(String optionName, String optionValue) {
this(optionName, null, optionValue);
}
OptionDef(String optionName, String optionKey, String optionValue) {
this.name = optionName;
this.key = optionKey;
this.value = optionValue;
}
}
/** the unique name of the configuration definition */
private final String mName;
/** a short description of the configuration definition */
private String mDescription = "";
public ConfigurationDef(String name) {
mName = name;
// use LinkedHashMap to keep objects in same order they were added.
mObjectClassMap = new LinkedHashMap<String, List<String>>();
mOptionList = new ArrayList<OptionDef>();
mClassFrequency = new HashMap<String, Integer>();
}
~~~
主要關注下面2個屬性:
mObjectClassMap:保存9大組件的,例如上面的build_provider、device_recovery、test、logger、result_reporter這些標簽對應的類都保持該map對象中。
mOptionList:保存option標簽的值,例如上面的enable-root的值。
現在進入debug模式驗證一下是不是用上面兩個屬性保存的。將斷點打在ConfigurationDef configDef = getConfigurationDef(configName, false);上,刪除其他斷點。重啟debug。按F6跳到下一行,來看一下Variables一欄中值:

可以看到mObjectClassMap的值為:
~~~
{build_provider=[com.android.cts.tradefed.build.CtsBuildProvider], device_recovery=[com.android.tradefed.device.WaitDeviceRecovery],
test=[com.android.cts.tradefed.testtype.CtsTest], logger=[com.android.tradefed.log.FileLogger],
result_reporter=[com.android.cts.tradefed.result.CtsXmlResultReporter, com.android.cts.tradefed.result.IssueReporter]}
~~~
和配置文件里的是一樣的,mOptionList也保存了xml中option對應的值:

然后通過configDef.createConfiguration();來創建Configuration對象。所以我們進入該方法它是如何將原生的替換為cts.xml中配置的:

將debug點跳轉到for循環中,然后在Variables一欄中分別查看this中的mObjectClassMap和config中mConfigMap的值:

可以看到mConfigMap是原生的,也就是Configuration的構造方法中添加的接口類,mObjectClassMap保存就是cts.xml配置文件里的接口類。然后根據Map的key值不能重復的特性用cts.xml配置的接口類替換掉原生的接口類。所以把斷點打在返回語句return上,按F8看結果:

這個時候可以看到mConfigMap的值變了:
~~~
{cmd_options=[com.android.tradefed.command.CommandOptions@7b2390],
device_requirements=[com.android.tradefed.device.DeviceSelectionOptions@5bd18b],
device_options=[com.android.tradefed.device.TestDeviceOptions@1a29fe],
target_preparer=[com.android.tradefed.targetprep.StubTargetPreparer@1beaa92],
build_provider=[com.android.cts.tradefed.build.CtsBuildProvider@c4f317],
device_recovery=[com.android.tradefed.device.WaitDeviceRecovery@33967b],
test=[com.android.cts.tradefed.testtype.CtsTest@7263d0],
logger=[com.android.tradefed.log.FileLogger@1a7422e],
result_reporter=[com.android.cts.tradefed.result.CtsXmlResultReporter@1750ae1, com.android.cts.tradefed.result.IssueReporter@b279f3]}
~~~
9大項全部配置完成。
- 前言
- (1)-windows下cts配置
- (2)-cts調試環境的搭建
- (3)-基礎庫tradefederation配置
- (4)-任務的添加
- (5)-9大組件配置
- (6)-任務的執行
- (7)-任務執行的調度室
- (8)-IBuildProvider
- (9)-IDeviceRecovery
- (10)-TestDeviceOptions
- (11)-ICommandOptions
- (12)-ITargetPreparer
- (13)-任務執行過程
- (14)-任務執行過程
- (15)-任務執行完
- (16)-logcat信息收集系統
- (17)-fastboot狀態監聽器
- (18)-設備恢復
- (19)-設備狀態的分類以及恢復模式的分類
- (20)-cts自身log系統
- (21)-測試結果收集系統
- (22)-自動檢測設備
- (23)-設備分類
- (24)-case的組織