# Fastboot狀態監聽器
## 類圖
涉及1個監聽器接口,2個實現類,1個執行線程。

## 解釋
這些類實際運用的是觀察者模式,所有的Listener都會被添加到Set中,然后執行線程FastbootMonitor每隔5秒鐘運行一次,來檢索目前處于fastboot狀態下的設備,然后更新設備狀態后,通知所有的listener,逐個調用listener的stateUpdated方法通知到各個listener。
## 代碼
監聽器接口IFastbootListener:
~~~
public static interface IFastbootListener {
/**
* Callback when fastboot state has been updated for all devices.
*/
public void stateUpdated();
}
~~~
2個實現類,都是DeviceStateMonitor類的私有類。
NotifyFastbootListener:通過Object類的notify通知在該對象上擁有鎖的且處于wait狀態的對象,你可以往下執行了。
~~~
private static class NotifyFastbootListener implements IFastbootListener {
@Override
public void stateUpdated() {
synchronized (this) {
notify();
}
}
}
~~~
StubFastbootListener:不做任何事
~~~
private static class StubFastbootListener implements IFastbootListener {
@Override
public void stateUpdated() {
// ignore
}
}
~~~
線程類FastbootMonitor,DeviceManager的私有類。
在該線程run方法中:
1.首先會通過cmd命令“fastboot devices”的執行結果,解析出處于fastboot的設備的SN號。
2.然后判斷可分配的設備中是否含有這些設備,如果有,需要更新這些設備的狀態至FASTBOOT。
3.接著要判斷已分配設備中是否含有這些設備,如果有,需要更新這些設備的狀態值NOT_AVAILABLE。(至于為什么和第2項中更新的不一樣,以后會講)。
4.通知所有監聽器,我已更新完當次的fastboot狀態。
~~~
private class FastbootMonitor extends Thread {
private boolean mQuit = false;
FastbootMonitor() {
super("FastbootMonitor");
}
public void terminate() {
mQuit = true;
interrupt();
}
@Override
public void run() {
while (!mQuit) {
// only poll fastboot devices if there are listeners, as polling
// it
// indiscriminately can cause fastboot commands to hang
if (!mFastbootListeners.isEmpty()) {
Set<String> serials = getDevicesOnFastboot();
if (serials != null) {
for (String serial : serials) {
IManagedTestDevice testDevice = mAllocatedDeviceMap.get(serial);
if (testDevice != null && !testDevice.getDeviceState().equals(TestDeviceState.FASTBOOT)) {
testDevice.setDeviceState(TestDeviceState.FASTBOOT);
}
}
// now update devices that are no longer on fastboot
synchronized (mAllocatedDeviceMap) {
for (IManagedTestDevice testDevice : mAllocatedDeviceMap.values()) {
if (!serials.contains(testDevice.getSerialNumber()) && testDevice.getDeviceState().equals(TestDeviceState.FASTBOOT)) {
testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE);
}
}
}
// create a copy of listeners for notification to
// prevent deadlocks
Collection<IFastbootListener> listenersCopy = new ArrayList<IFastbootListener>(mFastbootListeners.size());
listenersCopy.addAll(mFastbootListeners);
for (IFastbootListener listener : listenersCopy) {
listener.stateUpdated();
}
}
}
getRunUtil().sleep(FASTBOOT_POLL_WAIT_TIME);
}
}
}
private Set<String> getDevicesOnFastboot() {
CommandResult fastbootResult = getRunUtil().runTimedCmd(FASTBOOT_CMD_TIMEOUT, "fastboot", "devices");
if (fastbootResult.getStatus().equals(CommandStatus.SUCCESS)) {
CLog.v("fastboot devices returned\n %s", fastbootResult.getStdout());
return parseDevicesOnFastboot(fastbootResult.getStdout());
} else {
CLog.w("'fastboot devices' failed. Result: %s, stderr: %s", fastbootResult.getStatus(), fastbootResult.getStderr());
}
return null;
}
static Set<String> parseDevicesOnFastboot(String fastbootOutput) {
Set<String> serials = new HashSet<String>();
Pattern fastbootPattern = Pattern.compile("([\\w\\d]+)\\s+fastboot\\s*");
Matcher fastbootMatcher = fastbootPattern.matcher(fastbootOutput);
while (fastbootMatcher.find()) {
serials.add(fastbootMatcher.group(1));
}
return serials;
}
}
~~~
## 觀察者
哪些地方用到了這個狀態監聽器呢。也就是那些地方注冊成為了觀察者。很簡單,在DeviceManager類中找到addFastbootListener方法:

右鍵彈出對話框,點擊

就會找到有哪些地方用到了這個監聽器。

都在DeviceStateMonitor,其實想想也對,上面監聽器的2個實現類都是DeviceStateMonitor的私有類,別人也不能用。
~~~
/**
* {@inheritDoc}
*/
@Override
public boolean waitForDeviceBootloader(long time) {
if (!mFastbootEnabled) {
return false;
}
long startTime = System.currentTimeMillis();
// ensure fastboot state is updated at least once
waitForDeviceBootloaderStateUpdate();
long elapsedTime = System.currentTimeMillis() - startTime;
IFastbootListener listener = new StubFastbootListener();
mMgr.addFastbootListener(listener);
long waitTime = time - elapsedTime;
if (waitTime < 0) {
// wait at least 200ms
waitTime = 200;
}
boolean result = waitForDeviceState(TestDeviceState.FASTBOOT, waitTime);
mMgr.removeFastbootListener(listener);
return result;
}
~~~
~~~
@Override
public void waitForDeviceBootloaderStateUpdate() {
if (!mFastbootEnabled) {
return;
}
IFastbootListener listener = new NotifyFastbootListener();
synchronized (listener) {
mMgr.addFastbootListener(listener);
try {
listener.wait();
} catch (InterruptedException e) {
Log.w(LOG_TAG, "wait for device bootloader state update interrupted");
}
}
mMgr.removeFastbootListener(listener);
}
~~~
~~~
@Override
public boolean waitForDeviceNotAvailable(long waitTime) {
IFastbootListener listener = new StubFastbootListener();
if (mFastbootEnabled) {
mMgr.addFastbootListener(listener);
}
boolean result = waitForDeviceState(TestDeviceState.NOT_AVAILABLE, waitTime);
if (mFastbootEnabled) {
mMgr.removeFastbootListener(listener);
}
return result;
}
~~~
- 前言
- (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的組織