(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; } ~~~
';