(6)-任务的执行
最后更新于:2022-04-01 06:54:33
前两篇讲了任务的添加和9大项配置,这篇讲任务的执行。
# 任务的执行
任务的执行在CommandScheduler的run方法中,所以删除所有的断点,在run方法中打上断点,重启启动debug:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911dce563b8.jpg)
先看while循环下面的第一行代码
~~~
ExecutableCommand cmd = dequeueConfigCommand();
~~~
~~~
private ExecutableCommand dequeueConfigCommand() {
try {
// poll for a command, rather than block indefinitely, to handle shutdown case
return mCommandQueue.poll(getCommandPollTimeMs(), TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
CLog.i("Waiting for command interrupted");
}
return null;
}
~~~
从队列中取出第一个对象。如果队列中没有元素那就返回null。返回后,while中会判断如果为null的话,就会结束再次调用
~~~
ExecutableCommand cmd = dequeueConfigCommand();
~~~
直到cmd不为null。所以在
~~~
IDeviceSelection options = cmd.getConfiguration().getDeviceRequirements();
~~~
打上断点,按F8,程序会在cmd不为null时进入到上面的代码,停下来。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911dcea9e22.jpg)
首先得到系统设备要求,根据该要求,判断是否有满足要求的设备并分配该设备。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911dcedbbb4.jpg)
原生的 要求就一个S/N号,ddms会根据该SN号分配一个IDevice,然后cts根据IDevice包装成ITestDevice对象返回。然后根据ITestDevice,IDeviceManager和ExecutableCommand开始真正的启动任务。我们先不急于讨论执行的过程,而是继续向下看:
~~~
addInvocationThread(invThread);
if (cmd.isLoopMode()) {
addNewExecCommandToQueue(cmd.getCommandTracker());
}
~~~
先将正在执行的线程存到set中,然后将该命令再次放入任务队列中,这样的目的是为了能循环执行该任务。如果根据sn号没有分配成功ITestDevice,则会再次尝试一次,如果在规定时间内还没找到设备则放弃。最后做一些tearDown操作,然后将case运行过程中的log保存到文件。就算执行完了。
现在回头看一下执行任务的线程中是如何操作的:
~~~
private InvocationThread startInvocation(IDeviceManager manager, ITestDevice device,
ExecutableCommand cmd) {
final String invocationName = String.format("Invocation-%s", device.getSerialNumber());
InvocationThread invocationThread = new InvocationThread(invocationName, manager, device,
cmd);
invocationThread.start();
return invocationThread;
}
~~~
InvocationThread为CommandScheduler私有内部类,继承与线程,这就属于线程里启动线程。所以直接看InvocationThread的run方法就ok了。在run方法里调用了ITestInvocation的invoke方法:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911dcf07e9c.jpg)
传入的对象分别为ITestDevice、IConfiguration、IRescheduler。前两个已经涉及到,最后一个IRescheduler是什么?自己看吧,也没啥意义。这样任务的前期的工作都已经搞定了,程序转到了TestInvocation的invoke方法。放到下一篇文章来讲,因为它很重要,相当于一个调度室的作用。
# 总结
写了6篇,总结一些cts的过程。
任务的开始点是接受命令行中的参数,如果判断为执行cts任务,那么会在Console.run方法中启动添加命令任务的线程**ArgRunnable**和执行任务的线程**CommandScheduler**。添加任务线程**ArgRunnable**会调用**CommandScheduler**对象方法addCommand来向**ConditionPriorityBlockingQueue(采用先进先出的队列)**这个队列中添加,而执行任务线程**CommandScheduler**会通过调用自己的私有方法dequeueConfigCommand来从
**ConditionPriorityBlockingQueue**去取可执行的任务,每次取第一个。然后调用**InvocationThread**这个线程去执行任务。**InvocationThread**这个线程调用TestInvocation.invoke方法去执行任务。
明白了么,其实很简单!![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911dcf36bd4.gif)