(17)-fastboot状态监听器
最后更新于:2022-04-01 06:54:58
# Fastboot状态监听器
## 类图
涉及1个监听器接口,2个实现类,1个执行线程。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911ddc404eb.jpg)
## 解释
这些类实际运用的是观察者模式,所有的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方法:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911ddc54166.jpg)
右键弹出对话框,点击
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911ddc8971e.jpg)
就会找到有哪些地方用到了这个监听器。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-09_56911ddcec428.jpg)
都在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;
}
~~~